diff --git a/frontend/docs/API_INTEGRATION.md b/frontend/docs/API_INTEGRATION.md
new file mode 100644
index 0000000..bb97d24
--- /dev/null
+++ b/frontend/docs/API_INTEGRATION.md
@@ -0,0 +1,913 @@
+# API Integration Guide
+
+**Project**: Next.js + FastAPI Template
+**Version**: 1.0
+**Last Updated**: 2025-10-31
+
+---
+
+## Table of Contents
+
+1. [Quick Start](#1-quick-start)
+2. [Generating the API Client](#2-generating-the-api-client)
+3. [Making API Calls](#3-making-api-calls)
+4. [Authentication Integration](#4-authentication-integration)
+5. [Error Handling](#5-error-handling)
+6. [React Query Integration](#6-react-query-integration)
+7. [Testing API Integration](#7-testing-api-integration)
+8. [Common Patterns](#8-common-patterns)
+9. [Troubleshooting](#9-troubleshooting)
+
+---
+
+## 1. Quick Start
+
+### 1.1 Prerequisites
+
+1. Backend running at `http://localhost:8000`
+2. Frontend environment variables configured:
+ ```env
+ NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
+ NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
+ ```
+
+### 1.2 Generate API Client
+
+```bash
+cd frontend
+npm run generate:api
+```
+
+This fetches the OpenAPI spec from the backend and generates TypeScript types and API client functions.
+
+### 1.3 Make Your First API Call
+
+```typescript
+import { useQuery } from '@tanstack/react-query';
+import { apiClient } from '@/lib/api/client';
+
+function UserList() {
+ const { data, isLoading } = useQuery({
+ queryKey: ['users'],
+ queryFn: async () => {
+ const response = await apiClient.get('/users');
+ return response.data;
+ },
+ });
+
+ if (isLoading) return
Loading...
;
+ return {/* Render users */}
;
+}
+```
+
+---
+
+## 2. Generating the API Client
+
+### 2.1 Generation Script
+
+The generation script fetches the OpenAPI specification from the backend and creates TypeScript types and API client code.
+
+**Script Location**: `frontend/scripts/generate-api-client.sh`
+
+```bash
+#!/bin/bash
+set -e
+
+API_URL="${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8000}"
+OUTPUT_DIR="./src/lib/api/generated"
+
+echo "Fetching OpenAPI spec from $API_URL/api/v1/openapi.json..."
+
+npx @hey-api/openapi-ts \
+ --input "$API_URL/api/v1/openapi.json" \
+ --output "$OUTPUT_DIR" \
+ --client axios \
+ --types
+
+echo "✅ API client generated successfully in $OUTPUT_DIR"
+```
+
+### 2.2 Generated Files
+
+After running the script, you'll have:
+
+```
+src/lib/api/generated/
+├── index.ts # Main exports
+├── models/ # TypeScript interfaces for all models
+│ ├── User.ts
+│ ├── Organization.ts
+│ ├── UserSession.ts
+│ └── ...
+└── services/ # API service functions
+ ├── AuthService.ts
+ ├── UsersService.ts
+ ├── OrganizationsService.ts
+ └── ...
+```
+
+### 2.3 When to Regenerate
+
+Regenerate the API client when:
+- Backend API changes (new endpoints, updated models)
+- After pulling backend changes from git
+- When types don't match backend responses
+- As part of CI/CD pipeline
+
+---
+
+## 3. Making API Calls
+
+### 3.1 Using Generated Services
+
+**Example: Fetching users**
+```typescript
+import { UsersService } from '@/lib/api/generated';
+
+async function getUsers() {
+ const users = await UsersService.getUsers({
+ page: 1,
+ pageSize: 20,
+ search: 'john'
+ });
+ return users;
+}
+```
+
+**Example: Creating a user**
+```typescript
+import { AdminService } from '@/lib/api/generated';
+
+async function createUser(data: CreateUserDto) {
+ const newUser = await AdminService.createUser({
+ requestBody: data
+ });
+ return newUser;
+}
+```
+
+### 3.2 Using Axios Client Directly
+
+For more control, use the configured Axios instance:
+
+```typescript
+import { apiClient } from '@/lib/api/client';
+
+// GET request
+const response = await apiClient.get('/users', {
+ params: { page: 1, search: 'john' }
+});
+
+// POST request
+const response = await apiClient.post('/admin/users', {
+ email: 'user@example.com',
+ first_name: 'John',
+ password: 'secure123'
+});
+
+// PATCH request
+const response = await apiClient.patch(`/users/${userId}`, {
+ first_name: 'Jane'
+});
+
+// DELETE request
+await apiClient.delete(`/users/${userId}`);
+```
+
+### 3.3 Request Configuration
+
+**Timeouts:**
+```typescript
+const response = await apiClient.get('/users', {
+ timeout: 5000 // 5 seconds
+});
+```
+
+**Custom Headers:**
+```typescript
+const response = await apiClient.post('/users', data, {
+ headers: {
+ 'X-Custom-Header': 'value'
+ }
+});
+```
+
+**Request Cancellation:**
+```typescript
+const controller = new AbortController();
+
+const response = await apiClient.get('/users', {
+ signal: controller.signal
+});
+
+// Cancel the request
+controller.abort();
+```
+
+---
+
+## 4. Authentication Integration
+
+### 4.1 Automatic Token Injection
+
+The Axios client automatically adds the Authorization header to all requests:
+
+```typescript
+// src/lib/api/client.ts
+apiClient.interceptors.request.use(
+ (config) => {
+ const token = useAuthStore.getState().accessToken;
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ return config;
+ }
+);
+```
+
+You don't need to manually add auth headers - they're added automatically!
+
+### 4.2 Token Refresh Flow
+
+The response interceptor handles token refresh automatically:
+
+```typescript
+apiClient.interceptors.response.use(
+ (response) => response,
+ async (error) => {
+ const originalRequest = error.config;
+
+ // If 401 and haven't retried yet
+ if (error.response?.status === 401 && !originalRequest._retry) {
+ originalRequest._retry = true;
+
+ try {
+ // Refresh tokens
+ const refreshToken = getRefreshToken();
+ const { access_token, refresh_token } = await AuthService.refreshToken({
+ requestBody: { refresh_token: refreshToken }
+ });
+
+ // Update stored tokens
+ useAuthStore.getState().setTokens(access_token, refresh_token);
+
+ // Retry original request with new token
+ originalRequest.headers.Authorization = `Bearer ${access_token}`;
+ return apiClient.request(originalRequest);
+
+ } catch (refreshError) {
+ // Refresh failed - logout user
+ useAuthStore.getState().clearAuth();
+ window.location.href = '/login';
+ return Promise.reject(refreshError);
+ }
+ }
+
+ return Promise.reject(error);
+ }
+);
+```
+
+### 4.3 Login Example
+
+```typescript
+import { AuthService } from '@/lib/api/generated';
+import { useAuthStore } from '@/stores/authStore';
+
+async function login(email: string, password: string) {
+ try {
+ const response = await AuthService.login({
+ requestBody: { email, password }
+ });
+
+ // Store tokens and user
+ useAuthStore.getState().setTokens(
+ response.access_token,
+ response.refresh_token
+ );
+ useAuthStore.getState().setUser(response.user);
+
+ return response.user;
+ } catch (error) {
+ throw parseAPIError(error);
+ }
+}
+```
+
+---
+
+## 5. Error Handling
+
+### 5.1 Backend Error Format
+
+The backend returns structured errors:
+
+```typescript
+{
+ success: false,
+ errors: [
+ {
+ code: "AUTH_001",
+ message: "Invalid credentials",
+ field: "email"
+ }
+ ]
+}
+```
+
+### 5.2 Parsing Errors
+
+**Error Parser** (`src/lib/api/errors.ts`):
+```typescript
+import type { AxiosError } from 'axios';
+
+export interface APIError {
+ code: string;
+ message: string;
+ field?: string;
+}
+
+export interface APIErrorResponse {
+ success: false;
+ errors: APIError[];
+}
+
+export function parseAPIError(error: AxiosError): APIError[] {
+ // Backend structured errors
+ if (error.response?.data?.errors) {
+ return error.response.data.errors;
+ }
+
+ // Network errors
+ if (!error.response) {
+ return [{
+ code: 'NETWORK_ERROR',
+ message: 'Network error. Please check your connection.',
+ }];
+ }
+
+ // HTTP status errors
+ const status = error.response.status;
+ if (status === 403) {
+ return [{
+ code: 'FORBIDDEN',
+ message: "You don't have permission to perform this action.",
+ }];
+ }
+
+ if (status === 404) {
+ return [{
+ code: 'NOT_FOUND',
+ message: 'The requested resource was not found.',
+ }];
+ }
+
+ if (status === 429) {
+ return [{
+ code: 'RATE_LIMIT',
+ message: 'Too many requests. Please slow down.',
+ }];
+ }
+
+ if (status >= 500) {
+ return [{
+ code: 'SERVER_ERROR',
+ message: 'A server error occurred. Please try again later.',
+ }];
+ }
+
+ // Fallback
+ return [{
+ code: 'UNKNOWN',
+ message: error.message || 'An unexpected error occurred.',
+ }];
+}
+```
+
+### 5.3 Error Code Mapping
+
+**Error Messages** (`src/lib/api/errorMessages.ts`):
+```typescript
+export const ERROR_MESSAGES: Record = {
+ // Authentication errors (AUTH_xxx)
+ 'AUTH_001': 'Invalid email or password',
+ 'AUTH_002': 'Account is inactive',
+ 'AUTH_003': 'Invalid or expired token',
+
+ // User errors (USER_xxx)
+ 'USER_001': 'User not found',
+ 'USER_002': 'This email is already registered',
+ 'USER_003': 'Invalid user data',
+
+ // Validation errors (VAL_xxx)
+ 'VAL_001': 'Invalid input. Please check your data.',
+ 'VAL_002': 'Email format is invalid',
+ 'VAL_003': 'Password does not meet requirements',
+
+ // Organization errors (ORG_xxx)
+ 'ORG_001': 'Organization name already exists',
+ 'ORG_002': 'Organization not found',
+
+ // Permission errors (PERM_xxx)
+ 'PERM_001': 'Insufficient permissions',
+ 'PERM_002': 'Admin access required',
+
+ // Rate limiting (RATE_xxx)
+ 'RATE_001': 'Too many requests. Please try again later.',
+};
+
+export function getErrorMessage(code: string): string {
+ return ERROR_MESSAGES[code] || 'An error occurred';
+}
+```
+
+### 5.4 Displaying Errors
+
+**In React Query:**
+```typescript
+import { toast } from 'sonner';
+import { parseAPIError, getErrorMessage } from '@/lib/api/errors';
+
+export function useUpdateUser() {
+ return useMutation({
+ mutationFn: updateUserFn,
+ onError: (error: AxiosError) => {
+ const errors = parseAPIError(error);
+ const message = getErrorMessage(errors[0]?.code) || errors[0]?.message;
+ toast.error(message);
+ },
+ });
+}
+```
+
+**In Forms:**
+```typescript
+const onSubmit = async (data: FormData) => {
+ try {
+ await updateUser(data);
+ } catch (error) {
+ const errors = parseAPIError(error);
+
+ // Set field-specific errors
+ errors.forEach((err) => {
+ if (err.field) {
+ form.setError(err.field as any, {
+ message: getErrorMessage(err.code) || err.message,
+ });
+ }
+ });
+
+ // Set general error
+ if (errors.some(err => !err.field)) {
+ form.setError('root', {
+ message: errors.find(err => !err.field)?.message || 'An error occurred',
+ });
+ }
+ }
+};
+```
+
+---
+
+## 6. React Query Integration
+
+### 6.1 Creating Query Hooks
+
+**Pattern: One hook per operation**
+
+```typescript
+// src/lib/api/hooks/useUsers.ts
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import { UsersService, AdminService } from '@/lib/api/generated';
+import { toast } from 'sonner';
+
+// Query: List users
+export function useUsers(filters?: UserFilters) {
+ return useQuery({
+ queryKey: ['users', filters],
+ queryFn: () => UsersService.getUsers(filters),
+ staleTime: 60000, // 1 minute
+ });
+}
+
+// Query: Single user
+export function useUser(userId: string | undefined) {
+ return useQuery({
+ queryKey: ['users', userId],
+ queryFn: () => UsersService.getUser({ userId: userId! }),
+ enabled: !!userId, // Only run if userId exists
+ });
+}
+
+// Mutation: Create user
+export function useCreateUser() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (data: CreateUserDto) =>
+ AdminService.createUser({ requestBody: data }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User created successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to create user');
+ },
+ });
+}
+
+// Mutation: Update user
+export function useUpdateUser() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: ({ id, data }: { id: string; data: UpdateUserDto }) =>
+ UsersService.updateUser({ userId: id, requestBody: data }),
+ onSuccess: (_, { id }) => {
+ queryClient.invalidateQueries({ queryKey: ['users', id] });
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User updated successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to update user');
+ },
+ });
+}
+
+// Mutation: Delete user
+export function useDeleteUser() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (userId: string) =>
+ AdminService.deleteUser({ userId }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User deleted successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to delete user');
+ },
+ });
+}
+```
+
+### 6.2 Using Query Hooks in Components
+
+```typescript
+'use client';
+
+import { useUsers, useDeleteUser } from '@/lib/api/hooks/useUsers';
+
+export function UserList() {
+ const [search, setSearch] = useState('');
+ const { data: users, isLoading, error } = useUsers({ search });
+ const deleteUser = useDeleteUser();
+
+ const handleDelete = (userId: string) => {
+ if (confirm('Are you sure?')) {
+ deleteUser.mutate(userId);
+ }
+ };
+
+ if (isLoading) return ;
+ if (error) return ;
+
+ return (
+
+
setSearch(e.target.value)}
+ placeholder="Search users..."
+ />
+
+ {users?.map(user => (
+
+ {user.name}
+ handleDelete(user.id)}
+ disabled={deleteUser.isPending}
+ >
+ {deleteUser.isPending ? 'Deleting...' : 'Delete'}
+
+
+ ))}
+
+
+ );
+}
+```
+
+### 6.3 Optimistic Updates
+
+For instant UI feedback:
+
+```typescript
+export function useToggleUserActive() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: ({ userId, isActive }: { userId: string; isActive: boolean }) =>
+ AdminService.updateUser({
+ userId,
+ requestBody: { is_active: isActive }
+ }),
+ onMutate: async ({ userId, isActive }) => {
+ // Cancel outgoing refetches
+ await queryClient.cancelQueries({ queryKey: ['users', userId] });
+
+ // Snapshot previous value
+ const previousUser = queryClient.getQueryData(['users', userId]);
+
+ // Optimistically update
+ queryClient.setQueryData(['users', userId], (old: User) => ({
+ ...old,
+ is_active: isActive,
+ }));
+
+ return { previousUser };
+ },
+ onError: (err, variables, context) => {
+ // Rollback on error
+ if (context?.previousUser) {
+ queryClient.setQueryData(['users', variables.userId], context.previousUser);
+ }
+ toast.error('Failed to update user');
+ },
+ onSettled: (_, __, { userId }) => {
+ // Refetch to ensure consistency
+ queryClient.invalidateQueries({ queryKey: ['users', userId] });
+ },
+ });
+}
+```
+
+---
+
+## 7. Testing API Integration
+
+### 7.1 Mocking API Calls
+
+**Using MSW (Mock Service Worker):**
+
+```typescript
+// tests/mocks/handlers.ts
+import { rest } from 'msw';
+
+export const handlers = [
+ rest.get('/api/v1/users', (req, res, ctx) => {
+ return res(
+ ctx.json({
+ data: [
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' },
+ ],
+ pagination: {
+ total: 2,
+ page: 1,
+ page_size: 20,
+ total_pages: 1,
+ },
+ })
+ );
+ }),
+
+ rest.post('/api/v1/admin/users', async (req, res, ctx) => {
+ const body = await req.json();
+ return res(
+ ctx.json({
+ id: '3',
+ ...body,
+ })
+ );
+ }),
+
+ rest.delete('/api/v1/admin/users/:userId', (req, res, ctx) => {
+ return res(
+ ctx.json({ success: true, message: 'User deleted' })
+ );
+ }),
+];
+```
+
+### 7.2 Testing Query Hooks
+
+```typescript
+import { renderHook, waitFor } from '@testing-library/react';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+import { useUsers } from './useUsers';
+
+function createWrapper() {
+ const queryClient = new QueryClient();
+ return ({ children }: { children: React.ReactNode }) => (
+
+ {children}
+
+ );
+}
+
+test('fetches users successfully', async () => {
+ const { result } = renderHook(() => useUsers(), {
+ wrapper: createWrapper(),
+ });
+
+ await waitFor(() => expect(result.current.isSuccess).toBe(true));
+
+ expect(result.current.data).toHaveLength(2);
+ expect(result.current.data[0].name).toBe('John Doe');
+});
+```
+
+---
+
+## 8. Common Patterns
+
+### 8.1 Pagination
+
+```typescript
+export function useUsersPaginated(page: number = 1, pageSize: number = 20) {
+ return useQuery({
+ queryKey: ['users', { page, pageSize }],
+ queryFn: () => UsersService.getUsers({ page, pageSize }),
+ keepPreviousData: true, // Keep old data while fetching new page
+ });
+}
+
+// Component usage
+function UserList() {
+ const [page, setPage] = useState(1);
+ const { data, isLoading, isFetching } = useUsersPaginated(page);
+
+ return (
+
+ {isLoading ? (
+
+ ) : (
+ <>
+
+ {data?.data.map(user => {user.name} )}
+
+
setPage(p => p - 1)}
+ disabled={page === 1 || isFetching}
+ >
+ Previous
+
+
setPage(p => p + 1)}
+ disabled={!data?.pagination.has_next || isFetching}
+ >
+ Next
+
+ >
+ )}
+
+ );
+}
+```
+
+### 8.2 Infinite Scroll
+
+```typescript
+export function useUsersInfinite() {
+ return useInfiniteQuery({
+ queryKey: ['users', 'infinite'],
+ queryFn: ({ pageParam = 1 }) =>
+ UsersService.getUsers({ page: pageParam, pageSize: 20 }),
+ getNextPageParam: (lastPage) =>
+ lastPage.pagination.has_next ? lastPage.pagination.page + 1 : undefined,
+ });
+}
+
+// Component usage
+function InfiniteUserList() {
+ const {
+ data,
+ fetchNextPage,
+ hasNextPage,
+ isFetchingNextPage,
+ } = useUsersInfinite();
+
+ const allUsers = data?.pages.flatMap(page => page.data) ?? [];
+
+ return (
+
+
+ {allUsers.map(user => {user.name} )}
+
+ {hasNextPage && (
+
fetchNextPage()} disabled={isFetchingNextPage}>
+ {isFetchingNextPage ? 'Loading more...' : 'Load More'}
+
+ )}
+
+ );
+}
+```
+
+### 8.3 Dependent Queries
+
+```typescript
+function UserDetail({ userId }: { userId: string }) {
+ // First query
+ const { data: user } = useUser(userId);
+
+ // Second query depends on first
+ const { data: sessions } = useQuery({
+ queryKey: ['sessions', userId],
+ queryFn: () => SessionService.getUserSessions({ userId }),
+ enabled: !!user, // Only fetch when user is loaded
+ });
+
+ return (
+
+
{user?.name}
+
Active Sessions
+
+ {sessions?.map(session => {session.device_name} )}
+
+
+ );
+}
+```
+
+---
+
+## 9. Troubleshooting
+
+### 9.1 CORS Errors
+
+**Symptom**: `Access-Control-Allow-Origin` error in console
+
+**Solution**: Ensure backend CORS is configured for frontend URL:
+```python
+# backend/app/main.py
+BACKEND_CORS_ORIGINS = ["http://localhost:3000"]
+```
+
+### 9.2 401 Unauthorized
+
+**Symptom**: All API calls return 401
+
+**Possible Causes**:
+1. No token in store: Check `useAuthStore.getState().accessToken`
+2. Token expired: Check token expiration
+3. Token invalid: Try logging in again
+4. Interceptor not working: Check interceptor configuration
+
+**Debug**:
+```typescript
+// Log token in interceptor
+apiClient.interceptors.request.use((config) => {
+ const token = useAuthStore.getState().accessToken;
+ console.log('Token:', token ? 'Present' : 'Missing');
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ return config;
+});
+```
+
+### 9.3 Type Mismatches
+
+**Symptom**: TypeScript errors about response types
+
+**Solution**: Regenerate API client to sync with backend
+```bash
+npm run generate:api
+```
+
+### 9.4 Stale Data
+
+**Symptom**: UI shows old data after mutation
+
+**Solution**: Invalidate queries after mutations
+```typescript
+onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+}
+```
+
+### 9.5 Network Timeout
+
+**Symptom**: Requests timeout
+
+**Solution**: Increase timeout or check backend performance
+```typescript
+const apiClient = axios.create({
+ timeout: 60000, // 60 seconds
+});
+```
+
+---
+
+## Conclusion
+
+This guide covers the essential patterns for integrating with the FastAPI backend. For more advanced use cases, refer to:
+- [TanStack Query Documentation](https://tanstack.com/query/latest)
+- [Axios Documentation](https://axios-http.com/)
+- Backend API documentation at `/docs` endpoint
diff --git a/frontend/docs/ARCHITECTURE.md b/frontend/docs/ARCHITECTURE.md
new file mode 100644
index 0000000..e28937e
--- /dev/null
+++ b/frontend/docs/ARCHITECTURE.md
@@ -0,0 +1,1226 @@
+# Frontend Architecture Documentation
+
+**Project**: Next.js + FastAPI Template
+**Version**: 1.0
+**Last Updated**: 2025-10-31
+**Status**: Living Document
+
+---
+
+## Table of Contents
+
+1. [System Overview](#1-system-overview)
+2. [Technology Stack](#2-technology-stack)
+3. [Architecture Patterns](#3-architecture-patterns)
+4. [Data Flow](#4-data-flow)
+5. [State Management Strategy](#5-state-management-strategy)
+6. [Authentication Architecture](#6-authentication-architecture)
+7. [API Integration](#7-api-integration)
+8. [Routing Strategy](#8-routing-strategy)
+9. [Component Organization](#9-component-organization)
+10. [Testing Strategy](#10-testing-strategy)
+11. [Performance Considerations](#11-performance-considerations)
+12. [Security Architecture](#12-security-architecture)
+13. [Design Decisions & Rationale](#13-design-decisions--rationale)
+14. [Deployment Architecture](#14-deployment-architecture)
+
+---
+
+## 1. System Overview
+
+### 1.1 Purpose
+
+This frontend template provides a production-ready foundation for building modern web applications with Next.js 15 and FastAPI backend integration. It implements comprehensive authentication, admin dashboards, user management, and organization management out of the box.
+
+### 1.2 High-Level Architecture
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ Next.js Frontend │
+├─────────────────────────────────────────────────────────────┤
+│ App Router (RSC) │ Client Components │ API Routes │
+├────────────────────┼────────────────────┼──────────────────┤
+│ Pages & Layouts │ Interactive UI │ Middleware │
+│ (Server-side) │ (Client-side) │ (Auth Guards) │
+└─────────────────────────────────────────────────────────────┘
+ ↓ ↑
+ ┌──────────────────────┐
+ │ State Management │
+ ├──────────────────────┤
+ │ TanStack Query │ ← Server State
+ │ (React Query v5) │
+ ├──────────────────────┤
+ │ Zustand Stores │ ← Client State
+ │ (Auth, UI) │
+ └──────────────────────┘
+ ↓ ↑
+ ┌──────────────────────┐
+ │ API Client Layer │
+ ├──────────────────────┤
+ │ Axios Instance │
+ │ + Interceptors │
+ ├──────────────────────┤
+ │ Generated Client │
+ │ (OpenAPI → TS) │
+ └──────────────────────┘
+ ↓ ↑
+ ┌──────────────────────┐
+ │ FastAPI Backend │
+ │ /api/v1/* │
+ └──────────────────────┘
+```
+
+### 1.3 Key Features
+
+- **Authentication**: JWT-based with token rotation, per-device session tracking
+- **Admin Dashboard**: User management, organization management, analytics
+- **State Management**: TanStack Query for server state, Zustand for auth/UI
+- **Type Safety**: Full TypeScript with generated types from OpenAPI spec
+- **Component Library**: shadcn/ui with Radix UI primitives
+- **Testing**: 90%+ coverage target with Jest, React Testing Library, Playwright
+- **Accessibility**: WCAG 2.1 Level AA compliance
+- **Dark Mode**: Full theme support with Tailwind CSS
+
+---
+
+## 2. Technology Stack
+
+### 2.1 Core Framework
+
+**Next.js 15.x (App Router)**
+- **Why**: Modern React framework with RSC, excellent DX, optimized performance
+- **App Router**: Preferred over Pages Router for better data fetching, layouts, and streaming
+- **Server Components**: Default for better performance, client components for interactivity
+- **TypeScript**: Strict mode enabled for maximum type safety
+
+### 2.2 State Management
+
+**TanStack Query (React Query v5)**
+- **Purpose**: Server state management (all API data)
+- **Why**: Automatic caching, background refetching, request deduplication, optimistic updates
+- **Usage**: All data fetching goes through React Query hooks
+
+**Zustand 4.x**
+- **Purpose**: Client-only state (authentication, UI preferences)
+- **Why**: Minimal boilerplate, no Context API overhead, simple API
+- **Usage**: Auth store, UI store (sidebar, theme, modals)
+- **Philosophy**: Use sparingly, prefer server state via React Query
+
+### 2.3 UI Layer
+
+**shadcn/ui**
+- **Why**: Accessible components (Radix UI), customizable, copy-paste (not npm dependency)
+- **Components**: Button, Card, Dialog, Form, Input, Table, Toast, etc.
+- **Customization**: Tailwind-based, easy to adapt to design system
+
+**Tailwind CSS 4.x**
+- **Why**: Utility-first, excellent DX, small bundle size, dark mode support
+- **Strategy**: Class-based dark mode, mobile-first responsive design
+- **Customization**: Custom theme colors, design tokens
+
+**Recharts 2.x**
+- **Purpose**: Charts for admin dashboard
+- **Why**: React-native, composable, responsive, themed with Tailwind colors
+
+### 2.4 API Layer
+
+**@hey-api/openapi-ts**
+- **Purpose**: Generate TypeScript client from backend OpenAPI spec
+- **Why**: Type-safe API calls, auto-generated types matching backend
+- **Alternative**: Considered `openapi-typescript-codegen` but this is more actively maintained
+
+**Axios 1.x**
+- **Purpose**: HTTP client for API calls
+- **Why**: Interceptor support for auth, better error handling than fetch
+- **Usage**: Wrapped in generated API client, configured with auth interceptors
+
+### 2.5 Forms & Validation
+
+**react-hook-form 7.x**
+- **Purpose**: Form state management
+- **Why**: Excellent performance, minimal re-renders, great DX
+
+**Zod 3.x**
+- **Purpose**: Runtime type validation and schema definition
+- **Why**: Type inference, composable schemas, integrates with react-hook-form
+- **Usage**: All forms use Zod schemas with `zodResolver`
+
+### 2.6 Testing
+
+**Jest + React Testing Library**
+- **Purpose**: Unit and component tests
+- **Why**: Industry standard, excellent React support, accessibility-focused
+
+**Playwright**
+- **Purpose**: End-to-end testing
+- **Why**: Fast, reliable, multi-browser, great debugging tools
+- **Coverage Target**: 90%+ for template robustness
+
+### 2.7 Additional Libraries
+
+- **date-fns**: Date manipulation and formatting (lighter than moment.js)
+- **clsx** + **tailwind-merge**: Conditional class names with conflict resolution
+- **lucide-react**: Icon system (tree-shakeable, consistent design)
+
+---
+
+## 3. Architecture Patterns
+
+### 3.1 Layered Architecture
+
+Inspired by backend's 5-layer architecture, frontend follows similar separation of concerns:
+
+```
+┌────────────────────────────────────────────────────────────┐
+│ Layer 1: Pages & Layouts (app/*) │
+│ - Route definitions, page components, layouts │
+│ - Mostly Server Components, minimal logic │
+│ - Delegates to hooks and components │
+└────────────────────────────────────────────────────────────┘
+ ↓
+┌────────────────────────────────────────────────────────────┐
+│ Layer 2: React Hooks (hooks/, lib/api/hooks/) │
+│ - Custom hooks for component logic │
+│ - React Query hooks for data fetching │
+│ - Reusable logic extraction │
+└────────────────────────────────────────────────────────────┘
+ ↓
+┌────────────────────────────────────────────────────────────┐
+│ Layer 3: Services (services/) │
+│ - Business logic (if complex) │
+│ - Multi-step operations │
+│ - Data transformations │
+└────────────────────────────────────────────────────────────┘
+ ↓
+┌────────────────────────────────────────────────────────────┐
+│ Layer 4: API Client (lib/api/*) │
+│ - Axios instance with interceptors │
+│ - Generated API client from OpenAPI │
+│ - Error handling │
+└────────────────────────────────────────────────────────────┘
+ ↓
+┌────────────────────────────────────────────────────────────┐
+│ Layer 5: Types & Models (types/, lib/api/generated/) │
+│ - TypeScript interfaces │
+│ - Generated types from OpenAPI │
+│ - Validation schemas (Zod) │
+└────────────────────────────────────────────────────────────┘
+```
+
+**Key Rules:**
+- Pages/Layouts should NOT contain business logic
+- Components should NOT call API client directly (use hooks)
+- Hooks should NOT contain display logic
+- API client should NOT contain business logic
+- Types should NOT import from upper layers
+
+### 3.2 Component Patterns
+
+**Server Components by Default:**
+```typescript
+// app/(authenticated)/admin/users/page.tsx
+// Server Component - can fetch data directly
+export default async function UsersPage() {
+ // Could fetch data here, but we delegate to client components with React Query
+ return (
+
+
+
{/* Client Component with data fetching */}
+
+ );
+}
+```
+
+**Client Components for Interactivity:**
+```typescript
+// components/admin/UserTable.tsx
+'use client';
+
+import { useUsers } from '@/lib/api/hooks/useUsers';
+
+export function UserTable() {
+ const { data, isLoading, error } = useUsers();
+ // ... render logic
+}
+```
+
+**Composition Over Prop Drilling:**
+```typescript
+// Good: Use composition
+
+
+ Users
+
+
+
+
+
+
+// Avoid: Deep prop drilling
+ } />
+```
+
+### 3.3 Single Responsibility Principle
+
+Each module has one clear responsibility:
+
+- **Pages**: Routing and layout structure
+- **Components**: UI rendering and user interaction
+- **Hooks**: Data fetching and reusable logic
+- **Services**: Complex business logic (multi-step operations)
+- **API Client**: HTTP communication
+- **Stores**: Global client state
+- **Types**: Type definitions
+
+---
+
+## 4. Data Flow
+
+### 4.1 Request Flow (API Call)
+
+```
+┌──────────────┐
+│ User Action │ (e.g., Click "Save User")
+└──────┬───────┘
+ ↓
+┌──────────────────┐
+│ Component │ Calls hook: updateUser.mutate(data)
+└──────┬───────────┘
+ ↓
+┌──────────────────┐
+│ React Query Hook │ useMutation with API client call
+│ (useUpdateUser) │
+└──────┬───────────┘
+ ↓
+┌──────────────────┐
+│ API Client │ Axios PUT request with interceptors
+│ (Axios) │
+└──────┬───────────┘
+ ↓
+┌──────────────────┐
+│ Request │ Add Authorization header
+│ Interceptor │ token = authStore.accessToken
+└──────┬───────────┘
+ ↓
+┌──────────────────┐
+│ FastAPI Backend │ PUT /api/v1/users/{id}
+└──────┬───────────┘
+ ↓
+┌──────────────────┐
+│ Response │ Check status code
+│ Interceptor │ - 401: Refresh token → retry
+│ │ - 200: Parse success
+│ │ - 4xx/5xx: Parse error
+└──────┬───────────┘
+ ↓
+┌──────────────────┐
+│ React Query │ Cache invalidation
+│ │ queryClient.invalidateQueries(['users'])
+└──────┬───────────┘
+ ↓
+┌──────────────────┐
+│ Component │ Re-renders with updated data
+│ (via useUsers) │ Shows success toast
+└──────────────────┘
+```
+
+### 4.2 Authentication Flow
+
+```
+┌──────────────┐
+│ Login Form │ User enters email + password
+└──────┬───────┘
+ ↓
+┌──────────────────────┐
+│ authStore.login() │ Zustand action
+└──────┬───────────────┘
+ ↓
+┌──────────────────────┐
+│ API: POST /auth/login│ Backend validates credentials
+└──────┬───────────────┘
+ ↓
+┌──────────────────────┐
+│ Backend Response │ { access_token, refresh_token, user }
+└──────┬───────────────┘
+ ↓
+┌──────────────────────┐
+│ authStore.setTokens()│ Store tokens (sessionStorage + localStorage/cookie)
+│ authStore.setUser() │ Store user object
+└──────┬───────────────┘
+ ↓
+┌──────────────────────┐
+│ Axios Interceptor │ Now adds Authorization header to all requests
+└──────┬───────────────┘
+ ↓
+┌──────────────────────┐
+│ Redirect to Home │ User is authenticated
+└──────────────────────┘
+```
+
+**Token Refresh Flow (Automatic):**
+```
+API Request → 401 Response → Check if refresh token exists
+ ↓ Yes ↓ No
+POST /auth/refresh Redirect to Login
+ ↓
+New Tokens → Update Store → Retry Original Request
+```
+
+### 4.3 State Updates
+
+**Server State (React Query):**
+- Automatic background refetch
+- Cache invalidation on mutations
+- Optimistic updates where appropriate
+
+**Client State (Zustand):**
+- Direct store updates
+- No actions/reducers boilerplate
+- Subscriptions for components
+
+---
+
+## 5. State Management Strategy
+
+### 5.1 Philosophy
+
+**Use the Right Tool for the Right Job:**
+- Server data → TanStack Query
+- Auth & tokens → Zustand
+- UI state → Zustand (minimal)
+- Form state → react-hook-form
+- Component state → useState/useReducer
+
+**Avoid Redundancy:**
+- DON'T duplicate server data in Zustand
+- DON'T store API responses in global state
+- DO keep state as local as possible
+
+### 5.2 TanStack Query Configuration
+
+**Global Config** (`src/config/queryClient.ts`):
+```typescript
+export const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ staleTime: 60000, // 1 minute
+ cacheTime: 300000, // 5 minutes
+ retry: 3, // Retry failed requests
+ refetchOnWindowFocus: true, // Refetch on tab focus
+ refetchOnReconnect: true, // Refetch on network reconnect
+ },
+ mutations: {
+ retry: 1, // Retry mutations once
+ },
+ },
+});
+```
+
+**Query Key Structure:**
+```typescript
+['users'] // List all users
+['users', userId] // Single user
+['users', { page: 1, search: 'john' }] // Filtered list
+['organizations', orgId, 'members'] // Nested resource
+```
+
+### 5.3 Zustand Stores
+
+**Auth Store** (`src/stores/authStore.ts`):
+```typescript
+interface AuthStore {
+ user: User | null;
+ accessToken: string | null;
+ refreshToken: string | null;
+ isAuthenticated: boolean;
+ isLoading: boolean;
+ login: (credentials) => Promise;
+ logout: () => Promise;
+ logoutAll: () => Promise;
+ setTokens: (access, refresh) => void;
+ clearAuth: () => void;
+}
+```
+
+**UI Store** (`src/stores/uiStore.ts`):
+```typescript
+interface UIStore {
+ sidebarOpen: boolean;
+ theme: 'light' | 'dark' | 'system';
+ setSidebarOpen: (open: boolean) => void;
+ toggleSidebar: () => void;
+ setTheme: (theme) => void;
+}
+```
+
+**Store Guidelines:**
+- Keep stores small and focused
+- Use selectors for computed values
+- Persist to localStorage where appropriate
+- Document why Zustand over alternatives
+
+---
+
+## 6. Authentication Architecture
+
+### 6.1 Token Management Strategy
+
+**Two-Token System:**
+- **Access Token**: Short-lived (15 min), stored in memory/sessionStorage
+- **Refresh Token**: Long-lived (7 days), stored in httpOnly cookie (preferred) or localStorage
+
+**Token Storage Decision:**
+- **Primary**: httpOnly cookies (most secure, prevents XSS)
+- **Fallback**: localStorage with encryption wrapper (if cookies not feasible)
+- **Access Token**: sessionStorage or React state (short-lived, acceptable risk)
+
+**Token Rotation:**
+- On refresh, both tokens are rotated
+- Old refresh token is invalidated immediately
+- Prevents token replay attacks
+
+### 6.2 Per-Device Session Tracking
+
+Backend tracks sessions per device:
+- Each login creates a unique session with device info
+- Users can view all active sessions
+- Users can revoke individual sessions
+- Logout only affects current device
+- "Logout All" deactivates all sessions
+
+Frontend Implementation:
+- Session list page at `/settings/sessions`
+- Display device name, IP, location, last used
+- Highlight current session
+- Revoke button for non-current sessions
+
+### 6.3 Auth Guard Implementation
+
+**Layout-Based Protection:**
+```typescript
+// app/(authenticated)/layout.tsx
+export default function AuthenticatedLayout({ children }) {
+ return (
+
+
+ {children}
+
+
+ );
+}
+```
+
+**Permission Checks:**
+```typescript
+// app/(authenticated)/admin/layout.tsx
+export default function AdminLayout({ children }) {
+ const { user } = useAuth();
+
+ if (!user?.is_superuser) {
+ redirect('/403');
+ }
+
+ return {children} ;
+}
+```
+
+### 6.4 Security Best Practices
+
+1. **No tokens in localStorage** (access token in sessionStorage acceptable due to short expiry)
+2. **Always use HTTPS in production**
+3. **Automatic token refresh before expiry** (5 min threshold)
+4. **Clear all auth state on logout**
+5. **Validate token ownership** (backend checks JTI against session)
+6. **Rate limiting awareness** (handle 429 responses)
+7. **CSRF protection** (if not using cookies for main token)
+
+---
+
+## 7. API Integration
+
+### 7.1 OpenAPI Client Generation
+
+**Workflow:**
+```
+Backend OpenAPI Spec → @hey-api/openapi-ts → TypeScript Client
+(/api/v1/openapi.json) (src/lib/api/generated/)
+```
+
+**Generation Script** (`scripts/generate-api-client.sh`):
+```bash
+#!/bin/bash
+API_URL="${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8000}"
+npx @hey-api/openapi-ts \
+ --input "$API_URL/api/v1/openapi.json" \
+ --output ./src/lib/api/generated \
+ --client axios
+```
+
+**Benefits:**
+- Type-safe API calls
+- Auto-completion in IDE
+- Compile-time error checking
+- No manual type definition
+- Always in sync with backend
+
+### 7.2 Axios Configuration
+
+**Base Instance** (`src/lib/api/client.ts`):
+```typescript
+export const apiClient = axios.create({
+ baseURL: process.env.NEXT_PUBLIC_API_URL,
+ timeout: 30000,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+});
+```
+
+**Request Interceptor:**
+```typescript
+apiClient.interceptors.request.use(
+ (config) => {
+ const token = authStore.getState().accessToken;
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ return config;
+ },
+ (error) => Promise.reject(error)
+);
+```
+
+**Response Interceptor:**
+```typescript
+apiClient.interceptors.response.use(
+ (response) => response,
+ async (error) => {
+ if (error.response?.status === 401) {
+ // Try to refresh token
+ try {
+ await authStore.getState().refreshTokens();
+ // Retry original request
+ return apiClient.request(error.config);
+ } catch {
+ // Refresh failed, logout
+ authStore.getState().clearAuth();
+ window.location.href = '/login';
+ }
+ }
+ return Promise.reject(parseAPIError(error));
+ }
+);
+```
+
+### 7.3 Error Handling
+
+**Backend Error Format:**
+```typescript
+{
+ success: false,
+ errors: [
+ {
+ code: "AUTH_001",
+ message: "Invalid credentials",
+ field: "email"
+ }
+ ]
+}
+```
+
+**Frontend Error Parsing:**
+```typescript
+export function parseAPIError(error: AxiosError): APIError {
+ if (error.response?.data?.errors) {
+ return error.response.data.errors;
+ }
+ return [{
+ code: 'UNKNOWN',
+ message: 'An unexpected error occurred'
+ }];
+}
+```
+
+**Error Code Mapping:**
+```typescript
+const ERROR_MESSAGES = {
+ 'AUTH_001': 'Invalid email or password',
+ 'USER_002': 'This email is already registered',
+ 'VAL_001': 'Please check your input',
+ // ... all backend error codes
+};
+```
+
+### 7.4 React Query Hooks Pattern
+
+**Standard Pattern:**
+```typescript
+// lib/api/hooks/useUsers.ts
+export function useUsers(filters?: UserFilters) {
+ return useQuery({
+ queryKey: ['users', filters],
+ queryFn: () => UserService.getUsers(filters),
+ });
+}
+
+export function useUser(userId: string) {
+ return useQuery({
+ queryKey: ['users', userId],
+ queryFn: () => UserService.getUser(userId),
+ enabled: !!userId,
+ });
+}
+
+export function useUpdateUser() {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: ({ id, data }: { id: string; data: UpdateUserDto }) =>
+ UserService.updateUser(id, data),
+ onSuccess: (_, { id }) => {
+ queryClient.invalidateQueries({ queryKey: ['users', id] });
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User updated successfully');
+ },
+ onError: (error: APIError[]) => {
+ toast.error(error[0]?.message || 'Failed to update user');
+ },
+ });
+}
+```
+
+---
+
+## 8. Routing Strategy
+
+### 8.1 App Router Structure
+
+```
+app/
+├── (auth)/ # Auth route group (no auth layout)
+│ ├── layout.tsx
+│ ├── login/
+│ └── register/
+├── (authenticated)/ # Protected route group
+│ ├── layout.tsx # Auth guard + header/footer
+│ ├── page.tsx # Home
+│ ├── settings/
+│ │ ├── layout.tsx # Settings sidebar
+│ │ ├── profile/
+│ │ ├── password/
+│ │ └── sessions/
+│ └── admin/
+│ ├── layout.tsx # Admin sidebar + permission check
+│ ├── users/
+│ └── organizations/
+├── dev/ # Development-only routes
+│ ├── layout.tsx # NODE_ENV check
+│ └── components/
+├── layout.tsx # Root layout
+└── page.tsx # Public home
+```
+
+**Route Groups** (parentheses in folder name):
+- Organize routes without affecting URL
+- Apply different layouts to route subsets
+- Example: `(auth)` and `(authenticated)` have different layouts
+
+### 8.2 Layout Strategy
+
+**Root Layout** (`app/layout.tsx`):
+- HTML structure
+- React Query provider
+- Theme provider
+- Global metadata
+
+**Auth Layout** (`app/(auth)/layout.tsx`):
+- Centered form container
+- No header/footer
+- Minimal styling
+
+**Authenticated Layout** (`app/(authenticated)/layout.tsx`):
+- Auth guard (redirect if not authenticated)
+- Header with user menu
+- Main content area
+- Footer
+
+**Admin Layout** (`app/(authenticated)/admin/layout.tsx`):
+- Admin sidebar
+- Breadcrumbs
+- Admin permission check (is_superuser)
+
+### 8.3 Loading & Error States
+
+```
+app/(authenticated)/admin/users/
+├── page.tsx # Main page
+├── loading.tsx # Streaming UI / Suspense fallback
+└── error.tsx # Error boundary
+```
+
+**loading.tsx**: Displayed while page/component is loading
+**error.tsx**: Displayed when error occurs (with retry button)
+
+---
+
+## 9. Component Organization
+
+### 9.1 Directory Structure
+
+```
+components/
+├── ui/ # shadcn components (copy-paste)
+│ ├── button.tsx
+│ ├── card.tsx
+│ └── ...
+├── auth/ # Authentication components
+│ ├── LoginForm.tsx
+│ ├── RegisterForm.tsx
+│ └── AuthGuard.tsx
+├── admin/ # Admin-specific components
+│ ├── UserTable.tsx
+│ ├── UserForm.tsx
+│ ├── BulkActionBar.tsx
+│ └── ...
+├── settings/ # Settings page components
+│ ├── ProfileSettings.tsx
+│ ├── SessionManagement.tsx
+│ └── ...
+├── charts/ # Chart wrappers
+│ ├── BarChartCard.tsx
+│ └── ...
+├── layout/ # Layout components
+│ ├── Header.tsx
+│ ├── Sidebar.tsx
+│ └── ...
+└── common/ # Reusable components
+ ├── DataTable.tsx
+ ├── LoadingSpinner.tsx
+ └── ...
+```
+
+### 9.2 Component Guidelines
+
+**Naming:**
+- PascalCase for components: `UserTable.tsx`
+- Match file name with component name
+- One component per file
+
+**Structure:**
+```typescript
+// 1. Imports
+import { useState } from 'react';
+import { Button } from '@/components/ui/button';
+import { useUsers } from '@/lib/api/hooks/useUsers';
+
+// 2. Types
+interface UserTableProps {
+ filters?: UserFilters;
+}
+
+// 3. Component
+export function UserTable({ filters }: UserTableProps) {
+ // Hooks
+ const { data, isLoading } = useUsers(filters);
+ const [selectedIds, setSelectedIds] = useState([]);
+
+ // Derived state
+ const hasSelection = selectedIds.length > 0;
+
+ // Event handlers
+ const handleSelectAll = () => {
+ setSelectedIds(data?.map(u => u.id) || []);
+ };
+
+ // Render
+ if (isLoading) return ;
+
+ return (
+
+ {/* JSX */}
+
+ );
+}
+```
+
+**Best Practices:**
+- Prefer named exports over default exports
+- Destructure props in function signature
+- Extract complex logic to hooks
+- Keep components focused (single responsibility)
+- Use composition over prop drilling
+
+### 9.3 Styling Strategy
+
+**Tailwind Utility Classes:**
+```typescript
+
+ Click Me
+
+```
+
+**Conditional Classes with cn():**
+```typescript
+import { cn } from '@/lib/utils/cn';
+
+
+```
+
+**Dark Mode:**
+```typescript
+
+ Content
+
+```
+
+---
+
+## 10. Testing Strategy
+
+### 10.1 Testing Pyramid
+
+```
+ ┌─────────┐
+ / E2E Tests \ (10% - Critical flows)
+ / \
+ /_________________\
+ / \
+ / Integration Tests \ (30% - Component + API)
+ / \
+ /_________________________\
+ / \
+ / Unit Tests \ (60% - Hooks, Utils, Libs)
+ /_______________________________\
+```
+
+### 10.2 Test Categories
+
+**Unit Tests** (60% of suite):
+- Utilities (`lib/utils/`)
+- Custom hooks (`hooks/`)
+- Services (`services/`)
+- Pure functions
+
+**Component Tests** (30% of suite):
+- Reusable components (`components/`)
+- Forms with validation
+- User interactions
+- Accessibility
+
+**Integration Tests** (E2E with Playwright, 10% of suite):
+- Critical user flows:
+ - Login → Dashboard
+ - Admin: Create/Edit/Delete User
+ - Admin: Manage Organizations
+ - Session Management
+- Multi-page journeys
+- Real backend interaction (or mock server)
+
+### 10.3 Testing Tools
+
+**Jest + React Testing Library:**
+```typescript
+// UserTable.test.tsx
+import { render, screen } from '@testing-library/react';
+import { UserTable } from './UserTable';
+
+test('renders user table with data', async () => {
+ render( );
+ expect(await screen.findByText('John Doe')).toBeInTheDocument();
+});
+```
+
+**Playwright E2E:**
+```typescript
+// tests/e2e/auth.spec.ts
+test('user can login', async ({ page }) => {
+ await page.goto('/login');
+ await page.fill('[name="email"]', 'admin@example.com');
+ await page.fill('[name="password"]', 'password123');
+ await page.click('button[type="submit"]');
+ await expect(page).toHaveURL('/dashboard');
+});
+```
+
+### 10.4 Coverage Target
+
+**Goal: 90%+ Overall Coverage**
+- Unit tests: 95%+
+- Component tests: 85%+
+- Integration tests: Critical paths only
+
+**Justification for 90%:**
+- This is a template for production projects
+- High coverage ensures robustness
+- Confidence for extension and customization
+
+---
+
+## 11. Performance Considerations
+
+### 11.1 Optimization Strategies
+
+**Code Splitting:**
+```typescript
+// Dynamic imports for heavy components
+const AdminDashboard = dynamic(() => import('./AdminDashboard'), {
+ loading: () => ,
+});
+```
+
+**Image Optimization:**
+```typescript
+import Image from 'next/image';
+
+
+```
+
+**React Query Caching:**
+- Stale time: 1 minute (reduce unnecessary refetches)
+- Cache time: 5 minutes (keep data in memory)
+- Background refetch: Yes (keep data fresh)
+
+**Bundle Size Monitoring:**
+```bash
+npm run build && npm run analyze
+# Use webpack-bundle-analyzer to identify large dependencies
+```
+
+### 11.2 Performance Targets
+
+**Lighthouse Scores:**
+- Performance: >90
+- Accessibility: 100
+- Best Practices: >90
+- SEO: >90
+
+**Core Web Vitals:**
+- LCP (Largest Contentful Paint): <2.5s
+- FID (First Input Delay): <100ms
+- CLS (Cumulative Layout Shift): <0.1
+
+---
+
+## 12. Security Architecture
+
+### 12.1 Client-Side Security
+
+**XSS Prevention:**
+- React's default escaping (JSX)
+- Sanitize user input if rendering HTML
+- CSP headers (configured in backend)
+
+**Token Security:**
+- Access token: sessionStorage or memory (15 min expiry mitigates risk)
+- Refresh token: httpOnly cookie (preferred) or encrypted localStorage
+- Never log tokens to console in production
+
+**HTTPS Only:**
+- All production requests over HTTPS
+- Cookies with Secure flag
+- No mixed content
+
+### 12.2 Input Validation
+
+**Client-Side Validation:**
+- Zod schemas for all forms
+- Immediate feedback to users
+- Prevent malformed requests
+
+**Remember:**
+- Client validation is for UX
+- Backend validation is for security
+- Always trust backend, not client
+
+### 12.3 Dependency Security
+
+**Regular Audits:**
+```bash
+npm audit
+npm audit fix
+```
+
+**Automated Scanning:**
+- Dependabot (GitHub)
+- Snyk (CI/CD integration)
+
+---
+
+## 13. Design Decisions & Rationale
+
+### 13.1 Why Next.js App Router?
+
+**Pros:**
+- Server Components reduce client bundle
+- Better data fetching patterns
+- Streaming and Suspense built-in
+- Simpler layouts and error handling
+
+**Cons:**
+- Newer, less mature than Pages Router
+- Learning curve for team
+
+**Decision:** App Router is the future, worth the investment
+
+### 13.2 Why TanStack Query?
+
+**Alternatives Considered:**
+- SWR: Similar but less features
+- Redux Toolkit Query: Too much boilerplate for our use case
+- Apollo Client: Overkill for REST API
+
+**Why TanStack Query:**
+- Best-in-class caching and refetching
+- Framework-agnostic (not tied to Next.js)
+- Excellent DevTools
+- Optimistic updates out of the box
+
+### 13.3 Why Zustand over Redux?
+
+**Why NOT Redux:**
+- Too much boilerplate (actions, reducers, middleware)
+- We don't need time-travel debugging
+- Most state is server state (handled by React Query)
+
+**Why Zustand:**
+- Minimal API (easy to learn)
+- No Context API overhead
+- Can use outside React (interceptors)
+- Only ~1KB
+
+### 13.4 Why shadcn/ui over Component Libraries?
+
+**Alternatives Considered:**
+- Material-UI: Heavy, opinionated styling
+- Chakra UI: Good, but still an npm dependency
+- Ant Design: Too opinionated for template
+
+**Why shadcn/ui:**
+- Copy-paste (full control)
+- Accessible (Radix UI primitives)
+- Tailwind-based (consistent with our stack)
+- Customizable without ejecting
+
+### 13.5 Why Axios over Fetch?
+
+**Why NOT Fetch:**
+- No request/response interceptors
+- Manual timeout handling
+- Less ergonomic error handling
+
+**Why Axios:**
+- Interceptors (essential for auth)
+- Automatic JSON parsing
+- Better error handling
+- Request cancellation
+- Timeout configuration
+
+### 13.6 Token Storage Strategy
+
+**Decision: httpOnly Cookies (Primary), localStorage (Fallback)**
+
+**Why httpOnly Cookies:**
+- Most secure (not accessible to JavaScript)
+- Prevents XSS token theft
+- Automatic sending with requests (if CORS configured)
+
+**Why Fallback to localStorage:**
+- Simpler initial setup (no backend cookie handling)
+- Still secure with proper measures:
+ - Short access token expiry (15 min)
+ - Token rotation on refresh
+ - HTTPS only
+ - Encrypted wrapper (optional)
+
+**Implementation:**
+- Try httpOnly cookies first
+- Fall back to localStorage if not feasible
+- Document choice in code
+
+---
+
+## 14. Deployment Architecture
+
+### 14.1 Production Deployment
+
+**Recommended Platform: Vercel**
+- Native Next.js support
+- Edge functions for middleware
+- Automatic preview deployments
+- CDN with global edge network
+
+**Alternative: Docker**
+```dockerfile
+FROM node:20-alpine
+WORKDIR /app
+COPY package*.json ./
+RUN npm ci --only=production
+COPY . .
+RUN npm run build
+EXPOSE 3000
+CMD ["npm", "start"]
+```
+
+### 14.2 Environment Configuration
+
+**Development:**
+```env
+NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
+NODE_ENV=development
+```
+
+**Production:**
+```env
+NEXT_PUBLIC_API_URL=https://api.example.com/api/v1
+NODE_ENV=production
+```
+
+**Secrets:**
+- Never commit `.env.local`
+- Use platform-specific secret management (Vercel Secrets, Docker Secrets)
+
+### 14.3 CI/CD Pipeline
+
+```yaml
+# .github/workflows/ci.yml
+name: CI
+on: [push, pull_request]
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install dependencies
+ run: npm ci
+ - name: Run tests
+ run: npm test
+ - name: Run linter
+ run: npm run lint
+ - name: Type check
+ run: npm run type-check
+ - name: Build
+ run: npm run build
+```
+
+---
+
+## Conclusion
+
+This architecture document provides a comprehensive overview of the frontend system design, patterns, and decisions. It should serve as a reference for developers working on the project and guide future architectural decisions.
+
+For specific implementation details, refer to:
+- **CODING_STANDARDS.md**: Code style and conventions
+- **COMPONENT_GUIDE.md**: Component usage and patterns
+- **FEATURE_EXAMPLES.md**: Step-by-step feature implementation
+- **API_INTEGRATION.md**: Detailed API integration guide
+
+**Remember**: This is a living document. Update it as the architecture evolves.
diff --git a/frontend/docs/CODING_STANDARDS.md b/frontend/docs/CODING_STANDARDS.md
new file mode 100644
index 0000000..6ed0223
--- /dev/null
+++ b/frontend/docs/CODING_STANDARDS.md
@@ -0,0 +1,1290 @@
+# Frontend Coding Standards
+
+**Project**: Next.js + FastAPI Template
+**Version**: 1.0
+**Last Updated**: 2025-10-31
+**Status**: Enforced
+
+---
+
+## Table of Contents
+
+1. [TypeScript Standards](#1-typescript-standards)
+2. [React Component Standards](#2-react-component-standards)
+3. [Naming Conventions](#3-naming-conventions)
+4. [File Organization](#4-file-organization)
+5. [State Management](#5-state-management)
+6. [API Integration](#6-api-integration)
+7. [Form Handling](#7-form-handling)
+8. [Styling Standards](#8-styling-standards)
+9. [Error Handling](#9-error-handling)
+10. [Testing Standards](#10-testing-standards)
+11. [Accessibility Standards](#11-accessibility-standards)
+12. [Performance Best Practices](#12-performance-best-practices)
+13. [Security Best Practices](#13-security-best-practices)
+14. [Code Review Checklist](#14-code-review-checklist)
+
+---
+
+## 1. TypeScript Standards
+
+### 1.1 General Principles
+
+**✅ DO:**
+- Enable strict mode in `tsconfig.json`
+- Define explicit types for all function parameters and return values
+- Use TypeScript's type inference where obvious
+- Prefer `interface` for object shapes, `type` for unions/primitives
+- Use generics for reusable, type-safe components and functions
+
+**❌ DON'T:**
+- Use `any` (use `unknown` if type is truly unknown)
+- Use `as any` casts (refactor to proper types)
+- Use `@ts-ignore` or `@ts-nocheck` (fix the underlying issue)
+- Leave implicit `any` types
+
+### 1.2 Interfaces vs Types
+
+**Use `interface` for object shapes:**
+```typescript
+// ✅ Good
+interface User {
+ id: string;
+ name: string;
+ email: string;
+ isActive: boolean;
+}
+
+interface UserFormProps {
+ user?: User;
+ onSubmit: (data: User) => void;
+ isLoading?: boolean;
+}
+```
+
+**Use `type` for unions, intersections, and primitives:**
+```typescript
+// ✅ Good
+type UserRole = 'admin' | 'user' | 'guest';
+type UserId = string;
+type UserOrNull = User | null;
+type UserWithPermissions = User & { permissions: string[] };
+```
+
+### 1.3 Function Signatures
+
+**Always type function parameters and return values:**
+```typescript
+// ✅ Good
+function formatUserName(user: User): string {
+ return `${user.firstName} ${user.lastName}`;
+}
+
+async function fetchUser(id: string): Promise {
+ const response = await apiClient.get(`/users/${id}`);
+ return response.data;
+}
+
+// ❌ Bad
+function formatUserName(user) { // Implicit any
+ return `${user.firstName} ${user.lastName}`;
+}
+```
+
+### 1.4 Generics
+
+**Use generics for reusable, type-safe code:**
+```typescript
+// ✅ Good: Generic data table
+interface DataTableProps {
+ data: T[];
+ columns: Column[];
+ onRowClick?: (row: T) => void;
+}
+
+export function DataTable({ data, columns, onRowClick }: DataTableProps) {
+ // Implementation
+}
+
+// Usage is fully type-safe
+ data={users} columns={userColumns} />
+```
+
+### 1.5 Unknown vs Any
+
+**Use `unknown` for truly unknown types:**
+```typescript
+// ✅ Good: Force type checking
+function parseJSON(jsonString: string): unknown {
+ return JSON.parse(jsonString);
+}
+
+const result = parseJSON('{"name": "John"}');
+// Must narrow type before use
+if (typeof result === 'object' && result !== null && 'name' in result) {
+ console.log(result.name);
+}
+
+// ❌ Bad: Bypasses all type checking
+function parseJSON(jsonString: string): any {
+ return JSON.parse(jsonString);
+}
+```
+
+### 1.6 Type Guards
+
+**Create type guards for runtime type checking:**
+```typescript
+// ✅ Good
+function isUser(value: unknown): value is User {
+ return (
+ typeof value === 'object' &&
+ value !== null &&
+ 'id' in value &&
+ 'email' in value
+ );
+}
+
+// Usage
+if (isUser(data)) {
+ // TypeScript knows data is User here
+ console.log(data.email);
+}
+```
+
+### 1.7 Utility Types
+
+**Use TypeScript utility types:**
+```typescript
+// Partial - make all properties optional
+type UserUpdate = Partial;
+
+// Pick - select specific properties
+type UserPreview = Pick;
+
+// Omit - exclude specific properties
+type UserWithoutPassword = Omit;
+
+// Record - create object type with specific keys
+type UserRolePermissions = Record;
+
+// Extract - extract from union
+type AdminRole = Extract;
+
+// Exclude - exclude from union
+type NonAdminRole = Exclude;
+```
+
+---
+
+## 2. React Component Standards
+
+### 2.1 Component Structure
+
+**Standard component template:**
+```typescript
+// 1. Imports (React, external libs, internal, types, styles)
+'use client'; // If client component
+
+import { useState, useEffect } from 'react';
+import { useRouter } from 'next/navigation';
+import { Button } from '@/components/ui/button';
+import { useUsers } from '@/lib/api/hooks/useUsers';
+
+// 2. Types
+interface UserListProps {
+ initialFilters?: UserFilters;
+ onUserSelect?: (user: User) => void;
+ className?: string;
+}
+
+// 3. Component
+export function UserList({
+ initialFilters,
+ onUserSelect,
+ className
+}: UserListProps) {
+ // 3a. Hooks (state, effects, router, query)
+ const router = useRouter();
+ const [filters, setFilters] = useState(initialFilters);
+ const { data, isLoading, error } = useUsers(filters);
+
+ // 3b. Derived state
+ const hasUsers = data && data.length > 0;
+ const isEmpty = !isLoading && !hasUsers;
+
+ // 3c. Effects
+ useEffect(() => {
+ // Side effects
+ }, [dependencies]);
+
+ // 3d. Event handlers
+ const handleUserClick = (user: User) => {
+ onUserSelect?.(user);
+ };
+
+ // 3e. Render conditions
+ if (isLoading) return ;
+ if (error) return ;
+ if (isEmpty) return ;
+
+ // 3f. Main render
+ return (
+
+ {/* JSX */}
+
+ );
+}
+```
+
+### 2.2 Server Components vs Client Components
+
+**Server Components by default:**
+```typescript
+// ✅ Good: Server Component (default)
+// app/(authenticated)/users/page.tsx
+export default async function UsersPage() {
+ // Could fetch data here, but we use client components with React Query
+ return (
+
+ );
+}
+```
+
+**Client Components only when needed:**
+```typescript
+// ✅ Good: Client Component (interactive)
+'use client';
+
+import { useState } from 'react';
+import { useUsers } from '@/lib/api/hooks/useUsers';
+
+export function UserList() {
+ const [search, setSearch] = useState('');
+ const { data } = useUsers({ search });
+
+ return (
+
+ setSearch(e.target.value)} />
+ {/* Render users */}
+
+ );
+}
+```
+
+**When to use Client Components:**
+- Using React hooks (useState, useEffect, etc.)
+- Event handlers (onClick, onChange, etc.)
+- Browser APIs (window, document, localStorage)
+- React Context consumers
+
+### 2.3 Props
+
+**Always type props explicitly:**
+```typescript
+// ✅ Good: Explicit interface
+interface ButtonProps {
+ label: string;
+ onClick: () => void;
+ variant?: 'primary' | 'secondary';
+ disabled?: boolean;
+ className?: string;
+ children?: React.ReactNode;
+}
+
+export function Button({
+ label,
+ onClick,
+ variant = 'primary',
+ disabled = false,
+ className
+}: ButtonProps) {
+ // Implementation
+}
+```
+
+**Destructure props in function signature:**
+```typescript
+// ✅ Good
+function UserCard({ user, onEdit }: UserCardProps) {
+ return {user.name}
;
+}
+
+// ❌ Bad
+function UserCard(props: UserCardProps) {
+ return {props.user.name}
;
+}
+```
+
+**Allow className override:**
+```typescript
+// ✅ Good: Allow consumers to add classes
+interface CardProps {
+ title: string;
+ className?: string;
+}
+
+export function Card({ title, className }: CardProps) {
+ return (
+
+ {title}
+
+ );
+}
+```
+
+### 2.4 Composition Over Prop Drilling
+
+**Use composition patterns:**
+```typescript
+// ✅ Good: Composition
+
+
+ Users
+ Manage system users
+
+
+
+
+
+ Create User
+
+
+
+// ❌ Bad: Complex props
+ }
+ footerAction={Create User }
+/>
+```
+
+### 2.5 Named Exports vs Default Exports
+
+**Prefer named exports:**
+```typescript
+// ✅ Good: Named export
+export function UserList() {
+ // Implementation
+}
+
+// Easier to refactor, better IDE support, explicit imports
+import { UserList } from './UserList';
+
+// ❌ Avoid: Default export
+export default function UserList() {
+ // Implementation
+}
+
+// Can be renamed on import, less explicit
+import WhateverName from './UserList';
+```
+
+**Exception: Next.js pages must use default export**
+```typescript
+// pages and route handlers require default export
+export default function UsersPage() {
+ return Users
;
+}
+```
+
+### 2.6 Custom Hooks
+
+**Extract reusable logic:**
+```typescript
+// ✅ Good: Custom hook
+function useDebounce(value: T, delay: number): T {
+ const [debouncedValue, setDebouncedValue] = useState(value);
+
+ useEffect(() => {
+ const handler = setTimeout(() => {
+ setDebouncedValue(value);
+ }, delay);
+
+ return () => {
+ clearTimeout(handler);
+ };
+ }, [value, delay]);
+
+ return debouncedValue;
+}
+
+// Usage
+function SearchInput() {
+ const [search, setSearch] = useState('');
+ const debouncedSearch = useDebounce(search, 500);
+
+ const { data } = useUsers({ search: debouncedSearch });
+
+ return setSearch(e.target.value)} />;
+}
+```
+
+**Hook naming: Always prefix with "use":**
+```typescript
+// ✅ Good
+function useAuth() { }
+function useUsers() { }
+function useDebounce() { }
+
+// ❌ Bad
+function auth() { }
+function getUsers() { }
+```
+
+---
+
+## 3. Naming Conventions
+
+### 3.1 Files and Directories
+
+| Type | Convention | Example |
+|------|------------|---------|
+| Components | PascalCase | `UserTable.tsx`, `LoginForm.tsx` |
+| Hooks | camelCase with `use` prefix | `useAuth.ts`, `useDebounce.ts` |
+| Utilities | camelCase | `formatDate.ts`, `parseError.ts` |
+| Types | camelCase | `user.ts`, `api.ts` |
+| Constants | camelCase or UPPER_SNAKE_CASE | `constants.ts`, `API_ENDPOINTS.ts` |
+| Stores | camelCase with `Store` suffix | `authStore.ts`, `uiStore.ts` |
+| Services | camelCase with `Service` suffix | `authService.ts`, `adminService.ts` |
+| Pages (Next.js) | lowercase | `page.tsx`, `layout.tsx`, `loading.tsx` |
+
+### 3.2 Variables and Functions
+
+**Variables:**
+```typescript
+// ✅ Good: camelCase
+const userName = 'John';
+const isAuthenticated = true;
+const userList = [];
+
+// ❌ Bad
+const UserName = 'John'; // PascalCase for variable
+const user_name = 'John'; // snake_case
+```
+
+**Functions:**
+```typescript
+// ✅ Good: camelCase, descriptive verb + noun
+function getUserById(id: string): User { }
+function formatDate(date: Date): string { }
+function handleSubmit(data: FormData): void { }
+
+// ❌ Bad
+function User(id: string) { } // Looks like a class
+function get_user(id: string) { } // snake_case
+function gub(id: string) { } // Not descriptive
+```
+
+**Event Handlers:**
+```typescript
+// ✅ Good: handle + EventName
+const handleClick = () => { };
+const handleSubmit = () => { };
+const handleInputChange = () => { };
+
+// ❌ Bad
+const onClick = () => { }; // Confusing with prop name
+const submit = () => { };
+```
+
+**Boolean Variables:**
+```typescript
+// ✅ Good: is/has/should prefix
+const isLoading = true;
+const hasError = false;
+const shouldRedirect = true;
+const canEdit = false;
+
+// ❌ Bad
+const loading = true;
+const error = false;
+```
+
+### 3.3 Constants
+
+**Use UPPER_SNAKE_CASE for true constants:**
+```typescript
+// ✅ Good
+const MAX_RETRY_ATTEMPTS = 3;
+const API_BASE_URL = 'https://api.example.com';
+const DEFAULT_PAGE_SIZE = 20;
+
+// Constants object
+const USER_ROLES = {
+ ADMIN: 'admin',
+ USER: 'user',
+ GUEST: 'guest',
+} as const;
+```
+
+### 3.4 Types and Interfaces
+
+**PascalCase for types and interfaces:**
+```typescript
+// ✅ Good
+interface User { }
+interface UserFormProps { }
+type UserId = string;
+type UserRole = 'admin' | 'user';
+
+// ❌ Bad
+interface user { }
+interface user_form_props { }
+type userId = string;
+```
+
+---
+
+## 4. File Organization
+
+### 4.1 Import Order
+
+**Organize imports in this order:**
+```typescript
+// 1. React and Next.js
+import { useState, useEffect } from 'react';
+import { useRouter } from 'next/navigation';
+import Image from 'next/image';
+
+// 2. External libraries
+import { useQuery } from '@tanstack/react-query';
+import { toast } from 'sonner';
+import { format } from 'date-fns';
+
+// 3. Internal components (UI first, then features)
+import { Button } from '@/components/ui/button';
+import { Card } from '@/components/ui/card';
+import { UserTable } from '@/components/admin/UserTable';
+
+// 4. Internal hooks and utilities
+import { useAuth } from '@/hooks/useAuth';
+import { useUsers } from '@/lib/api/hooks/useUsers';
+import { cn } from '@/lib/utils/cn';
+
+// 5. Types
+import type { User, UserFilters } from '@/types/user';
+
+// 6. Styles (if any)
+import styles from './Component.module.css';
+```
+
+### 4.2 Co-location
+
+**Group related files together:**
+```
+components/admin/
+├── UserTable/
+│ ├── UserTable.tsx
+│ ├── UserTable.test.tsx
+│ ├── UserTableRow.tsx
+│ ├── UserTableFilters.tsx
+│ └── index.ts (re-export)
+```
+
+**Or flat structure for simpler components:**
+```
+components/admin/
+├── UserTable.tsx
+├── UserTable.test.tsx
+├── UserForm.tsx
+├── UserForm.test.tsx
+```
+
+### 4.3 Barrel Exports
+
+**Use index.ts for clean imports:**
+```typescript
+// components/ui/index.ts
+export { Button } from './button';
+export { Card, CardHeader, CardContent } from './card';
+export { Input } from './input';
+
+// Usage
+import { Button, Card, Input } from '@/components/ui';
+```
+
+---
+
+## 5. State Management
+
+### 5.1 State Placement
+
+**Keep state as local as possible:**
+```typescript
+// ✅ Good: Local state
+function UserFilter() {
+ const [search, setSearch] = useState('');
+ return setSearch(e.target.value)} />;
+}
+
+// ❌ Bad: Unnecessary global state
+// Don't put search in Zustand store
+```
+
+### 5.2 TanStack Query Usage
+
+**Standard query pattern:**
+```typescript
+// lib/api/hooks/useUsers.ts
+export function useUsers(filters?: UserFilters) {
+ return useQuery({
+ queryKey: ['users', filters],
+ queryFn: () => UserService.getUsers(filters),
+ staleTime: 60000, // 1 minute
+ });
+}
+
+// Component usage
+function UserList() {
+ const { data, isLoading, error, refetch } = useUsers({ search: 'john' });
+
+ if (isLoading) return ;
+ if (error) return ;
+
+ return {/* Render data */}
;
+}
+```
+
+**Standard mutation pattern:**
+```typescript
+// lib/api/hooks/useUsers.ts
+export function useUpdateUser() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: ({ id, data }: { id: string; data: UpdateUserDto }) =>
+ UserService.updateUser(id, data),
+ onSuccess: (_, { id }) => {
+ // Invalidate queries to trigger refetch
+ queryClient.invalidateQueries({ queryKey: ['users', id] });
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User updated successfully');
+ },
+ onError: (error: APIError[]) => {
+ toast.error(error[0]?.message || 'Failed to update user');
+ },
+ });
+}
+
+// Component usage
+function UserForm({ userId }: { userId: string }) {
+ const updateUser = useUpdateUser();
+
+ const handleSubmit = (data: UpdateUserDto) => {
+ updateUser.mutate({ id: userId, data });
+ };
+
+ return (
+
+ );
+}
+```
+
+**Query key structure:**
+```typescript
+// ✅ Good: Consistent query keys
+['users'] // List all
+['users', userId] // Single user
+['users', { search: 'john', page: 1 }] // Filtered list
+['organizations', orgId, 'members'] // Nested resource
+
+// ❌ Bad: Inconsistent
+['userList']
+['user-' + userId]
+['getUsersBySearch', 'john']
+```
+
+### 5.3 Zustand Store Pattern
+
+**Auth store example:**
+```typescript
+// stores/authStore.ts
+import { create } from 'zustand';
+import { persist } from 'zustand/middleware';
+
+interface AuthStore {
+ user: User | null;
+ accessToken: string | null;
+ isAuthenticated: boolean;
+
+ setUser: (user: User | null) => void;
+ setTokens: (accessToken: string, refreshToken: string) => void;
+ clearAuth: () => void;
+}
+
+export const useAuthStore = create()(
+ persist(
+ (set) => ({
+ user: null,
+ accessToken: null,
+ isAuthenticated: false,
+
+ setUser: (user) => set({ user, isAuthenticated: !!user }),
+
+ setTokens: (accessToken, refreshToken) => {
+ set({ accessToken });
+ // Store refresh token separately (localStorage or cookie)
+ localStorage.setItem('refreshToken', refreshToken);
+ },
+
+ clearAuth: () => {
+ set({ user: null, accessToken: null, isAuthenticated: false });
+ localStorage.removeItem('refreshToken');
+ },
+ }),
+ {
+ name: 'auth-storage',
+ partialize: (state) => ({ user: state.user }), // Only persist user
+ }
+ )
+);
+
+// Usage with selector (performance optimization)
+function UserAvatar() {
+ const user = useAuthStore((state) => state.user);
+ return ;
+}
+```
+
+**UI store example:**
+```typescript
+// stores/uiStore.ts
+interface UIStore {
+ sidebarOpen: boolean;
+ theme: 'light' | 'dark' | 'system';
+
+ setSidebarOpen: (open: boolean) => void;
+ toggleSidebar: () => void;
+ setTheme: (theme: 'light' | 'dark' | 'system') => void;
+}
+
+export const useUIStore = create()(
+ persist(
+ (set) => ({
+ sidebarOpen: true,
+ theme: 'system',
+
+ setSidebarOpen: (open) => set({ sidebarOpen: open }),
+ toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
+ setTheme: (theme) => set({ theme }),
+ }),
+ { name: 'ui-storage' }
+ )
+);
+```
+
+---
+
+## 6. API Integration
+
+### 6.1 API Client Structure
+
+**Axios instance configuration:**
+```typescript
+// lib/api/client.ts
+import axios from 'axios';
+import { useAuthStore } from '@/stores/authStore';
+
+export const apiClient = axios.create({
+ baseURL: process.env.NEXT_PUBLIC_API_URL,
+ timeout: 30000,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+});
+
+// Request interceptor
+apiClient.interceptors.request.use(
+ (config) => {
+ const token = useAuthStore.getState().accessToken;
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ return config;
+ },
+ (error) => Promise.reject(error)
+);
+
+// Response interceptor
+apiClient.interceptors.response.use(
+ (response) => response,
+ async (error) => {
+ if (error.response?.status === 401) {
+ // Handle token refresh
+ try {
+ await refreshToken();
+ return apiClient.request(error.config);
+ } catch {
+ useAuthStore.getState().clearAuth();
+ window.location.href = '/login';
+ }
+ }
+ return Promise.reject(parseAPIError(error));
+ }
+);
+```
+
+### 6.2 Error Handling
+
+**Parse API errors:**
+```typescript
+// lib/api/errors.ts
+export interface APIError {
+ code: string;
+ message: string;
+ field?: string;
+}
+
+export function parseAPIError(error: AxiosError): APIError[] {
+ if (error.response?.data?.errors) {
+ return error.response.data.errors;
+ }
+
+ return [{
+ code: 'UNKNOWN',
+ message: error.message || 'An unexpected error occurred',
+ }];
+}
+
+// Error code mapping
+export const ERROR_MESSAGES: Record = {
+ 'AUTH_001': 'Invalid email or password',
+ 'USER_002': 'This email is already registered',
+ 'VAL_001': 'Please check your input',
+ 'ORG_001': 'Organization name already exists',
+};
+
+export function getErrorMessage(code: string): string {
+ return ERROR_MESSAGES[code] || 'An error occurred';
+}
+```
+
+### 6.3 Hook Organization
+
+**One hook file per resource:**
+```typescript
+// lib/api/hooks/useUsers.ts
+export function useUsers(filters?: UserFilters) { }
+export function useUser(userId: string) { }
+export function useCreateUser() { }
+export function useUpdateUser() { }
+export function useDeleteUser() { }
+
+// lib/api/hooks/useOrganizations.ts
+export function useOrganizations() { }
+export function useOrganization(orgId: string) { }
+export function useCreateOrganization() { }
+// ...
+```
+
+---
+
+## 7. Form Handling
+
+### 7.1 Form Pattern with react-hook-form + Zod
+
+**Standard form implementation:**
+```typescript
+// components/auth/LoginForm.tsx
+'use client';
+
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+
+// 1. Define schema
+const loginSchema = z.object({
+ email: z.string().email('Invalid email address'),
+ password: z.string().min(8, 'Password must be at least 8 characters'),
+});
+
+type LoginFormData = z.infer;
+
+// 2. Component
+export function LoginForm() {
+ const form = useForm({
+ resolver: zodResolver(loginSchema),
+ defaultValues: {
+ email: '',
+ password: '',
+ },
+ });
+
+ // 3. Submit handler
+ const onSubmit = async (data: LoginFormData) => {
+ try {
+ await authService.login(data);
+ router.push('/dashboard');
+ } catch (error) {
+ form.setError('root', {
+ message: 'Invalid credentials',
+ });
+ }
+ };
+
+ // 4. Render
+ return (
+
+ );
+}
+```
+
+### 7.2 Form Validation
+
+**Complex validation with Zod:**
+```typescript
+const userSchema = z.object({
+ email: z.string().email('Invalid email'),
+ password: z
+ .string()
+ .min(8, 'Min 8 characters')
+ .regex(/[A-Z]/, 'Must contain uppercase')
+ .regex(/[0-9]/, 'Must contain number'),
+ confirmPassword: z.string(),
+ firstName: z.string().min(1, 'Required'),
+ lastName: z.string().optional(),
+ phoneNumber: z
+ .string()
+ .regex(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number')
+ .optional(),
+}).refine((data) => data.password === data.confirmPassword, {
+ message: 'Passwords do not match',
+ path: ['confirmPassword'],
+});
+```
+
+### 7.3 Form Accessibility
+
+**Always include labels and error messages:**
+```typescript
+
+ Email
+
+ {form.formState.errors.email && (
+
+ {form.formState.errors.email.message}
+
+ )}
+
+```
+
+---
+
+## 8. Styling Standards
+
+### 8.1 Tailwind CSS Usage
+
+**Use utility classes:**
+```typescript
+// ✅ Good
+
+ Click me
+
+
+// ❌ Bad: Inline styles
+
+ Click me
+
+```
+
+**Use cn() for conditional classes:**
+```typescript
+import { cn } from '@/lib/utils/cn';
+
+
+```
+
+### 8.2 Responsive Design
+
+**Mobile-first approach:**
+```typescript
+
+ Content
+
+```
+
+### 8.3 Dark Mode
+
+**Use dark mode classes:**
+```typescript
+
+ Content
+
+```
+
+---
+
+## 10. Testing Standards
+
+### 10.1 Test File Organization
+
+```
+src/
+├── components/
+│ ├── UserTable.tsx
+│ └── UserTable.test.tsx
+└── lib/
+ ├── utils/
+ │ ├── formatDate.ts
+ │ └── formatDate.test.ts
+```
+
+### 10.2 Test Naming
+
+**Use descriptive test names:**
+```typescript
+// ✅ Good
+test('displays user list when data is loaded', async () => {});
+test('shows loading spinner while fetching users', () => {});
+test('displays error message when API request fails', () => {});
+test('redirects to login when user is not authenticated', () => {});
+
+// ❌ Bad
+test('works', () => {});
+test('test1', () => {});
+test('renders', () => {});
+```
+
+### 10.3 Component Testing
+
+**Test user interactions, not implementation:**
+```typescript
+// UserTable.test.tsx
+import { render, screen, userEvent } from '@testing-library/react';
+import { UserTable } from './UserTable';
+
+test('allows user to search for users', async () => {
+ const user = userEvent.setup();
+ render( );
+
+ const searchInput = screen.getByPlaceholderText('Search users');
+ await user.type(searchInput, 'john');
+
+ expect(await screen.findByText('John Doe')).toBeInTheDocument();
+ expect(screen.queryByText('Jane Smith')).not.toBeInTheDocument();
+});
+```
+
+### 10.4 Accessibility Testing
+
+**Test with accessibility queries:**
+```typescript
+// Prefer getByRole over getByTestId
+const button = screen.getByRole('button', { name: 'Submit' });
+const heading = screen.getByRole('heading', { name: 'Users' });
+const textbox = screen.getByRole('textbox', { name: 'Email' });
+```
+
+---
+
+## 11. Accessibility Standards
+
+### 11.1 Semantic HTML
+
+```typescript
+// ✅ Good: Semantic
+
+
+
+ Title
+ Content
+
+
+
+
+// ❌ Bad: Div soup
+
+```
+
+### 11.2 ARIA Labels
+
+**Use ARIA when semantic HTML isn't enough:**
+```typescript
+
+
+
+
+
+ Loading...
+
+```
+
+### 11.3 Keyboard Navigation
+
+**Ensure all interactive elements are keyboard accessible:**
+```typescript
+ {
+ if (e.key === 'Enter' || e.key === ' ') {
+ handleClick();
+ }
+ }}
+>
+ Click me
+
+```
+
+---
+
+## 12. Performance Best Practices
+
+### 12.1 Code Splitting
+
+**Dynamic imports for heavy components:**
+```typescript
+import dynamic from 'next/dynamic';
+
+const HeavyChart = dynamic(() => import('./HeavyChart'), {
+ loading: () => ,
+ ssr: false,
+});
+```
+
+### 12.2 Memoization
+
+**Use React.memo for expensive renders:**
+```typescript
+export const UserCard = React.memo(function UserCard({ user }: UserCardProps) {
+ return {user.name}
;
+});
+```
+
+**Use useMemo for expensive calculations:**
+```typescript
+const sortedUsers = useMemo(() => {
+ return users.sort((a, b) => a.name.localeCompare(b.name));
+}, [users]);
+```
+
+### 12.3 Image Optimization
+
+**Always use Next.js Image component:**
+```typescript
+import Image from 'next/image';
+
+
+```
+
+---
+
+## 13. Security Best Practices
+
+### 13.1 Input Sanitization
+
+**Never render raw HTML:**
+```typescript
+// ✅ Good: React escapes by default
+{userInput}
+
+// ❌ Bad: XSS vulnerability
+
+```
+
+### 13.2 Environment Variables
+
+**Never commit secrets:**
+```typescript
+// ✅ Good: Use env variables
+const apiUrl = process.env.NEXT_PUBLIC_API_URL;
+
+// ❌ Bad: Hardcoded
+const apiUrl = 'https://api.example.com';
+```
+
+**Public vs Private:**
+- `NEXT_PUBLIC_*`: Exposed to browser
+- Other vars: Server-side only
+
+---
+
+## 14. Code Review Checklist
+
+**Before submitting PR:**
+- [ ] All tests pass
+- [ ] No TypeScript errors
+- [ ] ESLint passes
+- [ ] Code follows naming conventions
+- [ ] Components are typed
+- [ ] Accessibility considerations met
+- [ ] Error handling implemented
+- [ ] Loading states implemented
+- [ ] No console.log statements
+- [ ] No commented-out code
+- [ ] Documentation updated if needed
+
+---
+
+## Conclusion
+
+These standards ensure consistency, maintainability, and quality across the codebase. Follow them rigorously, and update this document as the project evolves.
+
+For specific patterns and examples, refer to:
+- **ARCHITECTURE.md**: System design and patterns
+- **COMPONENT_GUIDE.md**: Component usage and examples
+- **FEATURE_EXAMPLES.md**: Step-by-step implementation guides
diff --git a/frontend/docs/COMPONENT_GUIDE.md b/frontend/docs/COMPONENT_GUIDE.md
new file mode 100644
index 0000000..e56f544
--- /dev/null
+++ b/frontend/docs/COMPONENT_GUIDE.md
@@ -0,0 +1,802 @@
+# Component Guide
+
+**Project**: Next.js + FastAPI Template
+**Version**: 1.0
+**Last Updated**: 2025-10-31
+
+---
+
+## Table of Contents
+
+1. [shadcn/ui Components](#1-shadcn-ui-components)
+2. [Custom Components](#2-custom-components)
+3. [Component Composition](#3-component-composition)
+4. [Customization](#4-customization)
+5. [Accessibility](#5-accessibility)
+
+---
+
+## 1. shadcn/ui Components
+
+### 1.1 Overview
+
+This project uses [shadcn/ui](https://ui.shadcn.com), a collection of accessible, customizable components built on Radix UI primitives. Components are copied into the project (not installed as npm dependencies), giving you full control.
+
+**Installation Method:**
+```bash
+npx shadcn@latest add button card input table dialog
+```
+
+### 1.2 Core Components
+
+#### Button
+
+```typescript
+import { Button } from '@/components/ui/button';
+
+// Variants
+Default
+Delete
+Cancel
+Ghost
+Link
+
+// Sizes
+Default
+Small
+Large
+
+
+// States
+Disabled
+Loading...
+
+// As Link
+
+ View Users
+
+```
+
+#### Card
+
+```typescript
+import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@/components/ui/card';
+
+
+
+ Users
+ Manage system users
+
+
+ Card content goes here
+
+
+ Action
+
+
+```
+
+#### Dialog / Modal
+
+```typescript
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogTrigger } from '@/components/ui/dialog';
+
+
+
+ Open Dialog
+
+
+
+ Delete User
+
+ Are you sure you want to delete this user? This action cannot be undone.
+
+
+
+ Cancel
+ Delete
+
+
+
+```
+
+#### Form
+
+```typescript
+import { Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage } from '@/components/ui/form';
+import { Input } from '@/components/ui/input';
+import { useForm } from 'react-hook-form';
+
+const form = useForm();
+
+
+
+```
+
+#### Table
+
+```typescript
+import { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell } from '@/components/ui/table';
+
+
+
+
+ Name
+ Email
+ Role
+
+
+
+ {users.map((user) => (
+
+ {user.name}
+ {user.email}
+ {user.role}
+
+ ))}
+
+
+```
+
+#### Toast / Notifications
+
+```typescript
+import { toast } from 'sonner';
+
+// Success
+toast.success('User created successfully');
+
+// Error
+toast.error('Failed to delete user');
+
+// Info
+toast.info('Processing your request...');
+
+// Loading
+toast.loading('Saving changes...');
+
+// Custom
+toast('Event has been created', {
+ description: 'Monday, January 3rd at 6:00pm',
+ action: {
+ label: 'Undo',
+ onClick: () => console.log('Undo'),
+ },
+});
+```
+
+#### Tabs
+
+```typescript
+import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
+
+
+
+ Profile
+ Password
+ Sessions
+
+
+
+
+
+
+
+
+
+
+
+```
+
+---
+
+## 2. Custom Components
+
+### 2.1 Layout Components
+
+#### Header
+
+```typescript
+import { Header } from '@/components/layout/Header';
+
+// Usage (in layout.tsx)
+
+
+// Features:
+// - Logo/brand
+// - Navigation links
+// - User menu (avatar, name, dropdown)
+// - Theme toggle
+// - Mobile menu button
+```
+
+#### PageContainer
+
+```typescript
+import { PageContainer } from '@/components/layout/PageContainer';
+
+
+ Page Title
+ Page content...
+
+
+// Provides:
+// - Consistent padding
+// - Max-width container
+// - Responsive layout
+```
+
+#### PageHeader
+
+```typescript
+import { PageHeader } from '@/components/common/PageHeader';
+
+Create User}
+/>
+```
+
+### 2.2 Data Display Components
+
+#### DataTable
+
+Generic, reusable data table with sorting, filtering, and pagination.
+
+```typescript
+import { DataTable } from '@/components/common/DataTable';
+import { ColumnDef } from '@tanstack/react-table';
+
+// Define columns
+const columns: ColumnDef[] = [
+ {
+ accessorKey: 'name',
+ header: 'Name',
+ },
+ {
+ accessorKey: 'email',
+ header: 'Email',
+ },
+ {
+ id: 'actions',
+ cell: ({ row }) => (
+ handleEdit(row.original)}>Edit
+ ),
+ },
+];
+
+// Use DataTable
+
+```
+
+#### LoadingSpinner
+
+```typescript
+import { LoadingSpinner } from '@/components/common/LoadingSpinner';
+
+// Sizes
+
+
+
+
+// With text
+
+ Loading users...
+
+```
+
+#### EmptyState
+
+```typescript
+import { EmptyState } from '@/components/common/EmptyState';
+
+ }
+ title="No users found"
+ description="Get started by creating a new user"
+ action={
+ router.push('/admin/users/new')}>
+ Create User
+
+ }
+/>
+```
+
+### 2.3 Admin Components
+
+#### UserTable
+
+```typescript
+import { UserTable } from '@/components/admin/UserTable';
+
+ console.log(user)}
+/>
+
+// Features:
+// - Search
+// - Filters (role, status)
+// - Sorting
+// - Pagination
+// - Bulk selection
+// - Bulk actions (activate, deactivate, delete)
+```
+
+#### UserForm
+
+```typescript
+import { UserForm } from '@/components/admin/UserForm';
+
+// Create mode
+ router.push('/admin/users')}
+/>
+
+// Edit mode
+ toast.success('User updated')}
+/>
+
+// Features:
+// - Validation with Zod
+// - Field errors
+// - Loading states
+// - Cancel/Submit actions
+```
+
+#### OrganizationTable
+
+```typescript
+import { OrganizationTable } from '@/components/admin/OrganizationTable';
+
+
+
+// Features:
+// - Search
+// - Member count display
+// - Actions (edit, delete, view members)
+```
+
+#### BulkActionBar
+
+```typescript
+import { BulkActionBar } from '@/components/admin/BulkActionBar';
+
+ handleBulkAction(action, selectedUserIds)}
+ onClearSelection={() => setSelectedUserIds([])}
+ actions={[
+ { value: 'activate', label: 'Activate' },
+ { value: 'deactivate', label: 'Deactivate' },
+ { value: 'delete', label: 'Delete', variant: 'destructive' },
+ ]}
+/>
+
+// Displays:
+// - Selection count
+// - Action dropdown
+// - Confirmation dialogs
+// - Progress indicators
+```
+
+### 2.4 Settings Components
+
+#### ProfileSettings
+
+```typescript
+import { ProfileSettings } from '@/components/settings/ProfileSettings';
+
+ console.log('Updated:', updatedUser)}
+/>
+
+// Fields:
+// - First name, last name
+// - Email (readonly)
+// - Phone number
+// - Avatar upload (optional)
+// - Preferences
+```
+
+#### PasswordSettings
+
+```typescript
+import { PasswordSettings } from '@/components/settings/PasswordSettings';
+
+
+
+// Fields:
+// - Current password
+// - New password
+// - Confirm password
+// - Option to logout all other devices
+```
+
+#### SessionManagement
+
+```typescript
+import { SessionManagement } from '@/components/settings/SessionManagement';
+
+
+
+// Features:
+// - List all active sessions
+// - Current session badge
+// - Device icons
+// - Location display
+// - Last used timestamp
+// - Revoke session button
+// - Logout all other devices button
+```
+
+#### SessionCard
+
+```typescript
+import { SessionCard } from '@/components/settings/SessionCard';
+
+ revokeSession(session.id)}
+/>
+
+// Displays:
+// - Device icon (desktop/mobile/tablet)
+// - Device name
+// - Location (city, country)
+// - IP address
+// - Last used (relative time)
+// - "This device" badge if current
+// - Revoke button (disabled for current)
+```
+
+### 2.5 Chart Components
+
+#### BarChartCard
+
+```typescript
+import { BarChartCard } from '@/components/charts/BarChartCard';
+
+
+```
+
+#### LineChartCard
+
+```typescript
+import { LineChartCard } from '@/components/charts/LineChartCard';
+
+
+```
+
+#### PieChartCard
+
+```typescript
+import { PieChartCard } from '@/components/charts/PieChartCard';
+
+
+```
+
+---
+
+## 3. Component Composition
+
+### 3.1 Form + Dialog Pattern
+
+```typescript
+
+
+
+ Create User
+
+ Add a new user to the system
+
+
+ {
+ setIsOpen(false);
+ queryClient.invalidateQueries(['users']);
+ }}
+ onCancel={() => setIsOpen(false)}
+ />
+
+
+```
+
+### 3.2 Card + Table Pattern
+
+```typescript
+
+
+
+
+ Users
+ Manage system users
+
+
router.push('/admin/users/new')}>
+ Create User
+
+
+
+
+
+
+
+```
+
+### 3.3 Tabs + Settings Pattern
+
+```typescript
+
+
+ Account Settings
+
+
+
+
+ Profile
+ Password
+ Sessions
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 3.4 Bulk Actions Pattern
+
+```typescript
+function UserList() {
+ const [selectedIds, setSelectedIds] = useState([]);
+ const { data: users } = useUsers();
+
+ return (
+
+ {selectedIds.length > 0 && (
+ setSelectedIds([])}
+ />
+ )}
+
+
+ );
+}
+```
+
+---
+
+## 4. Customization
+
+### 4.1 Theming
+
+Colors are defined in `tailwind.config.ts` using CSS variables:
+
+```typescript
+// tailwind.config.ts
+export default {
+ theme: {
+ extend: {
+ colors: {
+ border: 'hsl(var(--border))',
+ background: 'hsl(var(--background))',
+ foreground: 'hsl(var(--foreground))',
+ primary: {
+ DEFAULT: 'hsl(var(--primary))',
+ foreground: 'hsl(var(--primary-foreground))',
+ },
+ // ...
+ },
+ },
+ },
+};
+```
+
+**Customize colors in `globals.css`:**
+```css
+@layer base {
+ :root {
+ --primary: 222.2 47.4% 11.2%;
+ --primary-foreground: 210 40% 98%;
+ /* ... */
+ }
+
+ .dark {
+ --primary: 210 40% 98%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+ /* ... */
+ }
+}
+```
+
+### 4.2 Component Variants
+
+Add new variants to existing components:
+
+```typescript
+// components/ui/button.tsx
+const buttonVariants = cva(
+ 'base-classes',
+ {
+ variants: {
+ variant: {
+ default: '...',
+ destructive: '...',
+ outline: '...',
+ // Add custom variant
+ success: 'bg-green-600 text-white hover:bg-green-700',
+ },
+ },
+ }
+);
+
+// Usage
+Activate
+```
+
+### 4.3 Extending Components
+
+Create wrapper components:
+
+```typescript
+// components/common/ConfirmDialog.tsx
+interface ConfirmDialogProps {
+ title: string;
+ description: string;
+ confirmLabel?: string;
+ onConfirm: () => void;
+ onCancel: () => void;
+}
+
+export function ConfirmDialog({
+ title,
+ description,
+ confirmLabel = 'Confirm',
+ onConfirm,
+ onCancel,
+}: ConfirmDialogProps) {
+ return (
+
+
+
+ {title}
+ {description}
+
+
+
+ Cancel
+
+
+ {confirmLabel}
+
+
+
+
+ );
+}
+```
+
+---
+
+## 5. Accessibility
+
+### 5.1 Keyboard Navigation
+
+All shadcn/ui components support keyboard navigation:
+- `Tab`: Move focus
+- `Enter`/`Space`: Activate
+- `Escape`: Close dialogs/dropdowns
+- Arrow keys: Navigate lists/menus
+
+### 5.2 Screen Reader Support
+
+Components include proper ARIA labels:
+
+```typescript
+
+
+
+
+
+ Loading users...
+
+
+
+```
+
+### 5.3 Focus Management
+
+Dialog components automatically manage focus:
+- Focus trap inside dialog
+- Return focus on close
+- Focus first focusable element
+
+### 5.4 Color Contrast
+
+All theme colors meet WCAG 2.1 Level AA standards:
+- Normal text: 4.5:1 contrast ratio
+- Large text: 3:1 contrast ratio
+
+---
+
+## Conclusion
+
+This guide covers the essential components in the project. For more details:
+- **shadcn/ui docs**: https://ui.shadcn.com
+- **Radix UI docs**: https://www.radix-ui.com
+- **TanStack Table docs**: https://tanstack.com/table
+- **Recharts docs**: https://recharts.org
+
+For implementation examples, see `FEATURE_EXAMPLES.md`.
diff --git a/frontend/docs/FEATURE_EXAMPLES.md b/frontend/docs/FEATURE_EXAMPLES.md
new file mode 100644
index 0000000..c9fe754
--- /dev/null
+++ b/frontend/docs/FEATURE_EXAMPLES.md
@@ -0,0 +1,1059 @@
+# Feature Implementation Examples
+
+**Project**: Next.js + FastAPI Template
+**Version**: 1.0
+**Last Updated**: 2025-10-31
+
+---
+
+## Table of Contents
+
+1. [Example 1: User Management Feature](#example-1-user-management-feature)
+2. [Example 2: Session Management Feature](#example-2-session-management-feature)
+3. [Example 3: Adding Charts to Admin Dashboard](#example-3-adding-charts-to-admin-dashboard)
+
+---
+
+## Example 1: User Management Feature
+
+This example shows how to implement a complete user management feature with list, create, edit, and delete functionality.
+
+### Step 1: Create API Hooks
+
+**File**: `src/lib/api/hooks/useUsers.ts`
+
+```typescript
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import { UsersService, AdminService } from '@/lib/api/generated';
+import type { User, CreateUserDto, UpdateUserDto } from '@/lib/api/generated/models';
+import { toast } from 'sonner';
+import { parseAPIError } from '@/lib/api/errors';
+
+export interface UserFilters {
+ search?: string;
+ is_active?: boolean;
+ is_superuser?: boolean;
+ page?: number;
+ page_size?: number;
+}
+
+// Query: List users
+export function useUsers(filters?: UserFilters) {
+ return useQuery({
+ queryKey: ['users', filters],
+ queryFn: async () => {
+ const response = await AdminService.getUsers({
+ search: filters?.search,
+ isActive: filters?.is_active,
+ isSuperuser: filters?.is_superuser,
+ page: filters?.page || 1,
+ pageSize: filters?.page_size || 20,
+ });
+ return response;
+ },
+ staleTime: 60000, // 1 minute
+ });
+}
+
+// Query: Single user
+export function useUser(userId: string | undefined) {
+ return useQuery({
+ queryKey: ['users', userId],
+ queryFn: () => AdminService.getUser({ userId: userId! }),
+ enabled: !!userId,
+ });
+}
+
+// Mutation: Create user
+export function useCreateUser() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (data: CreateUserDto) =>
+ AdminService.createUser({ requestBody: data }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User created successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to create user');
+ },
+ });
+}
+
+// Mutation: Update user
+export function useUpdateUser() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: ({ id, data }: { id: string; data: UpdateUserDto }) =>
+ AdminService.updateUser({ userId: id, requestBody: data }),
+ onSuccess: (_, { id }) => {
+ queryClient.invalidateQueries({ queryKey: ['users', id] });
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User updated successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to update user');
+ },
+ });
+}
+
+// Mutation: Delete user
+export function useDeleteUser() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (userId: string) =>
+ AdminService.deleteUser({ userId }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User deleted successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to delete user');
+ },
+ });
+}
+
+// Mutation: Activate/Deactivate user
+export function useToggleUserActive() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: ({ userId, isActive }: { userId: string; isActive: boolean }) =>
+ AdminService[isActive ? 'activateUser' : 'deactivateUser']({ userId }),
+ onSuccess: (_, { userId }) => {
+ queryClient.invalidateQueries({ queryKey: ['users', userId] });
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('User status updated');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to update user status');
+ },
+ });
+}
+
+// Mutation: Bulk actions
+export function useBulkUserAction() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: ({ action, userIds }: { action: string; userIds: string[] }) =>
+ AdminService.bulkUserAction({
+ requestBody: { action, user_ids: userIds }
+ }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ toast.success('Bulk action completed successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to perform bulk action');
+ },
+ });
+}
+```
+
+### Step 2: Create User Table Component
+
+**File**: `src/components/admin/UserTable.tsx`
+
+```typescript
+'use client';
+
+import { useState } from 'react';
+import { useRouter } from 'next/navigation';
+import { useUsers, useDeleteUser, useBulkUserAction } from '@/lib/api/hooks/useUsers';
+import { DataTable } from '@/components/common/DataTable';
+import { Button } from '@/components/ui/button';
+import { Badge } from '@/components/ui/badge';
+import { BulkActionBar } from '@/components/admin/BulkActionBar';
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from '@/components/ui/dropdown-menu';
+import { MoreHorizontal, Pencil, Trash2 } from 'lucide-react';
+import type { ColumnDef } from '@tanstack/react-table';
+import type { User } from '@/lib/api/generated/models';
+
+export function UserTable() {
+ const router = useRouter();
+ const [selectedIds, setSelectedIds] = useState([]);
+ const [filters, setFilters] = useState({
+ search: '',
+ page: 1,
+ });
+
+ const { data, isLoading } = useUsers(filters);
+ const deleteUser = useDeleteUser();
+ const bulkAction = useBulkUserAction();
+
+ const columns: ColumnDef[] = [
+ {
+ id: 'select',
+ header: ({ table }) => (
+ table.toggleAllPageRowsSelected(!!value)}
+ />
+ ),
+ cell: ({ row }) => (
+ row.toggleSelected(!!value)}
+ />
+ ),
+ },
+ {
+ accessorKey: 'first_name',
+ header: 'Name',
+ cell: ({ row }) => (
+
+
+ {row.original.first_name} {row.original.last_name}
+
+
+ {row.original.email}
+
+
+ ),
+ },
+ {
+ accessorKey: 'is_active',
+ header: 'Status',
+ cell: ({ row }) => (
+
+ {row.original.is_active ? 'Active' : 'Inactive'}
+
+ ),
+ },
+ {
+ accessorKey: 'is_superuser',
+ header: 'Role',
+ cell: ({ row }) => (
+
+ {row.original.is_superuser ? 'Admin' : 'User'}
+
+ ),
+ },
+ {
+ accessorKey: 'created_at',
+ header: 'Created',
+ cell: ({ row }) => new Date(row.original.created_at).toLocaleDateString(),
+ },
+ {
+ id: 'actions',
+ cell: ({ row }) => (
+
+
+
+
+
+
+
+ router.push(`/admin/users/${row.original.id}`)}
+ >
+
+ Edit
+
+ handleDelete(row.original.id)}
+ >
+
+ Delete
+
+
+
+ ),
+ },
+ ];
+
+ const handleDelete = async (userId: string) => {
+ if (confirm('Are you sure you want to delete this user?')) {
+ deleteUser.mutate(userId);
+ }
+ };
+
+ const handleBulkAction = async (action: string) => {
+ bulkAction.mutate({ action, userIds: selectedIds });
+ setSelectedIds([]);
+ };
+
+ return (
+
+ {selectedIds.length > 0 && (
+ setSelectedIds([])}
+ />
+ )}
+
+ setFilters({ ...filters, page })}
+ onRowSelectionChange={setSelectedIds}
+ />
+
+ );
+}
+```
+
+### Step 3: Create User Form Component
+
+**File**: `src/components/admin/UserForm.tsx`
+
+```typescript
+'use client';
+
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { useCreateUser, useUpdateUser } from '@/lib/api/hooks/useUsers';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+import { Checkbox } from '@/components/ui/checkbox';
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from '@/components/ui/form';
+import type { User } from '@/lib/api/generated/models';
+
+const userSchema = z.object({
+ email: z.string().email('Invalid email address'),
+ password: z.string().min(8, 'Password must be at least 8 characters').optional(),
+ first_name: z.string().min(1, 'First name is required'),
+ last_name: z.string().optional(),
+ phone_number: z.string().optional(),
+ is_active: z.boolean().default(true),
+ is_superuser: z.boolean().default(false),
+});
+
+type UserFormData = z.infer;
+
+interface UserFormProps {
+ user?: User;
+ onSuccess?: () => void;
+ onCancel?: () => void;
+}
+
+export function UserForm({ user, onSuccess, onCancel }: UserFormProps) {
+ const createUser = useCreateUser();
+ const updateUser = useUpdateUser();
+
+ const form = useForm({
+ resolver: zodResolver(userSchema),
+ defaultValues: user || {
+ email: '',
+ first_name: '',
+ last_name: '',
+ phone_number: '',
+ is_active: true,
+ is_superuser: false,
+ },
+ });
+
+ const onSubmit = async (data: UserFormData) => {
+ try {
+ if (user) {
+ await updateUser.mutateAsync({ id: user.id, data });
+ } else {
+ await createUser.mutateAsync(data);
+ }
+ onSuccess?.();
+ } catch (error) {
+ // Error handling is done in hooks
+ }
+ };
+
+ return (
+
+
+ );
+}
+```
+
+### Step 4: Create User List Page
+
+**File**: `src/app/(authenticated)/admin/users/page.tsx`
+
+```typescript
+import { Metadata } from 'next';
+import { Button } from '@/components/ui/button';
+import { PageHeader } from '@/components/common/PageHeader';
+import { UserTable } from '@/components/admin/UserTable';
+import Link from 'next/link';
+
+export const metadata: Metadata = {
+ title: 'User Management',
+ description: 'Manage application users',
+};
+
+export default function UsersPage() {
+ return (
+
+
+ Create User
+
+ }
+ />
+
+
+
+ );
+}
+```
+
+### Step 5: Create User Detail Page
+
+**File**: `src/app/(authenticated)/admin/users/[id]/page.tsx`
+
+```typescript
+import { Metadata } from 'next';
+import { UserForm } from '@/components/admin/UserForm';
+import { PageHeader } from '@/components/common/PageHeader';
+
+export const metadata: Metadata = {
+ title: 'Edit User',
+ description: 'Edit user details',
+};
+
+export default function UserDetailPage({ params }: { params: { id: string } }) {
+ return (
+
+ );
+}
+```
+
+### Step 6: Create New User Page
+
+**File**: `src/app/(authenticated)/admin/users/new/page.tsx`
+
+```typescript
+import { Metadata } from 'next';
+import { UserForm } from '@/components/admin/UserForm';
+import { PageHeader } from '@/components/common/PageHeader';
+
+export const metadata: Metadata = {
+ title: 'Create User',
+ description: 'Add a new user',
+};
+
+export default function NewUserPage() {
+ return (
+
+ );
+}
+```
+
+### Testing the Feature
+
+**Test the user management flow:**
+1. Navigate to `/admin/users`
+2. Search for users
+3. Click "Create User" and fill the form
+4. Edit an existing user
+5. Delete a user (with confirmation)
+6. Test bulk actions (select multiple users, activate/deactivate)
+7. Test pagination
+
+---
+
+## Example 2: Session Management Feature
+
+This example shows how to implement per-device session management.
+
+### Step 1: Create Session Hooks
+
+**File**: `src/lib/api/hooks/useSessions.ts`
+
+```typescript
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import { SessionsService } from '@/lib/api/generated';
+import { toast } from 'sonner';
+import { parseAPIError } from '@/lib/api/errors';
+
+// Query: List my sessions
+export function useMySessions() {
+ return useQuery({
+ queryKey: ['sessions', 'me'],
+ queryFn: () => SessionsService.getMySessions(),
+ refetchInterval: 30000, // Refetch every 30 seconds
+ });
+}
+
+// Mutation: Revoke session
+export function useRevokeSession() {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (sessionId: string) =>
+ SessionsService.revokeSession({ sessionId }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['sessions'] });
+ toast.success('Session revoked successfully');
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to revoke session');
+ },
+ });
+}
+
+// Mutation: Logout all devices
+export function useLogoutAllDevices() {
+ return useMutation({
+ mutationFn: () => AuthService.logoutAll(),
+ onSuccess: () => {
+ // This will logout the user
+ useAuthStore.getState().clearAuth();
+ window.location.href = '/login';
+ },
+ onError: (error) => {
+ const errors = parseAPIError(error);
+ toast.error(errors[0]?.message || 'Failed to logout all devices');
+ },
+ });
+}
+```
+
+### Step 2: Create Session Card Component
+
+**File**: `src/components/settings/SessionCard.tsx`
+
+```typescript
+'use client';
+
+import { Button } from '@/components/ui/button';
+import { Card, CardContent } from '@/components/ui/card';
+import { Badge } from '@/components/ui/badge';
+import { Monitor, Smartphone, Tablet } from 'lucide-react';
+import { formatDistanceToNow } from 'date-fns';
+import type { UserSession } from '@/lib/api/generated/models';
+
+interface SessionCardProps {
+ session: UserSession;
+ onRevoke: () => void;
+ isRevoking?: boolean;
+}
+
+export function SessionCard({ session, onRevoke, isRevoking }: SessionCardProps) {
+ const getDeviceIcon = () => {
+ const deviceName = session.device_name?.toLowerCase() || '';
+ if (deviceName.includes('mobile') || deviceName.includes('iphone')) {
+ return ;
+ }
+ if (deviceName.includes('tablet') || deviceName.includes('ipad')) {
+ return ;
+ }
+ return ;
+ };
+
+ const getLocation = () => {
+ const parts = [];
+ if (session.location_city) parts.push(session.location_city);
+ if (session.location_country) parts.push(session.location_country);
+ return parts.join(', ') || 'Unknown location';
+ };
+
+ return (
+
+
+
+
+ {getDeviceIcon()}
+
+
+
+
+
+ {session.device_name || 'Unknown Device'}
+
+ {session.is_current && (
+
This device
+ )}
+
+
+
+ {getLocation()}
+
+
+
+ IP: {session.ip_address || 'Unknown'}
+
+
+
+ Last used {formatDistanceToNow(new Date(session.last_used_at))} ago
+
+
+
+
+
+ {isRevoking ? 'Revoking...' : 'Revoke'}
+
+
+
+ );
+}
+```
+
+### Step 3: Create Session Management Component
+
+**File**: `src/components/settings/SessionManagement.tsx`
+
+```typescript
+'use client';
+
+import { useState } from 'react';
+import { useMySessions, useRevokeSession, useLogoutAllDevices } from '@/lib/api/hooks/useSessions';
+import { SessionCard } from './SessionCard';
+import { Button } from '@/components/ui/button';
+import { LoadingSpinner } from '@/components/common/LoadingSpinner';
+import { EmptyState } from '@/components/common/EmptyState';
+import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-dialog';
+import { Smartphone } from 'lucide-react';
+
+export function SessionManagement() {
+ const [showLogoutAllDialog, setShowLogoutAllDialog] = useState(false);
+ const { data: sessions, isLoading } = useMySessions();
+ const revokeSession = useRevokeSession();
+ const logoutAll = useLogoutAllDevices();
+
+ const otherSessions = sessions?.filter(s => !s.is_current) || [];
+
+ if (isLoading) {
+ return ;
+ }
+
+ return (
+
+
+
+
Active Sessions
+
+ Manage your active sessions across devices
+
+
+
+ {otherSessions.length > 0 && (
+
setShowLogoutAllDialog(true)}
+ >
+ Logout All Other Devices
+
+ )}
+
+
+
+ {sessions?.map(session => (
+ revokeSession.mutate(session.id)}
+ isRevoking={revokeSession.isPending}
+ />
+ ))}
+
+
+ {sessions?.length === 0 && (
+
}
+ title="No active sessions"
+ description="You don't have any active sessions"
+ />
+ )}
+
+
+
+
+ Logout All Other Devices?
+
+ This will log you out of all other devices. You'll remain logged in on this device.
+
+
+
+ Cancel
+ logoutAll.mutate()}>
+ Logout All
+
+
+
+
+
+ );
+}
+```
+
+### Step 4: Create Sessions Page
+
+**File**: `src/app/(authenticated)/settings/sessions/page.tsx`
+
+```typescript
+import { Metadata } from 'next';
+import { SessionManagement } from '@/components/settings/SessionManagement';
+
+export const metadata: Metadata = {
+ title: 'Sessions',
+ description: 'Manage your active sessions',
+};
+
+export default function SessionsPage() {
+ return ;
+}
+```
+
+---
+
+## Example 3: Adding Charts to Admin Dashboard
+
+This example shows how to add charts to the admin dashboard.
+
+### Step 1: Create Chart Components (if not exists)
+
+**File**: `src/components/charts/LineChartCard.tsx`
+
+```typescript
+import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@/components/ui/card';
+import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
+
+interface LineChartCardProps {
+ title: string;
+ description?: string;
+ data: any[];
+ dataKey: string;
+ xAxisKey: string;
+ color?: string;
+}
+
+export function LineChartCard({
+ title,
+ description,
+ data,
+ dataKey,
+ xAxisKey,
+ color = 'hsl(var(--primary))',
+}: LineChartCardProps) {
+ return (
+
+
+ {title}
+ {description && {description} }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+```
+
+### Step 2: Create Admin Stats Hook
+
+**File**: `src/lib/api/hooks/useAdminStats.ts`
+
+```typescript
+import { useQuery } from '@tanstack/react-query';
+import { apiClient } from '@/lib/api/client';
+
+export interface AdminStats {
+ total_users: number;
+ active_users: number;
+ total_organizations: number;
+ user_growth: Array<{ date: string; count: number }>;
+ org_growth: Array<{ date: string; count: number }>;
+}
+
+export function useAdminStats() {
+ return useQuery({
+ queryKey: ['admin', 'stats'],
+ queryFn: async () => {
+ const response = await apiClient.get('/admin/stats');
+ return response.data;
+ },
+ staleTime: 300000, // 5 minutes
+ });
+}
+```
+
+### Step 3: Create Admin Dashboard Page
+
+**File**: `src/app/(authenticated)/admin/page.tsx`
+
+```typescript
+import { Metadata } from 'next';
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
+import { LineChartCard } from '@/components/charts/LineChartCard';
+import { Users, Building, UserCheck } from 'lucide-react';
+
+export const metadata: Metadata = {
+ title: 'Admin Dashboard',
+ description: 'Admin statistics and overview',
+};
+
+// Note: This would be a client component in real implementation
+// to use useAdminStats hook
+export default function AdminDashboardPage() {
+ // const { data: stats, isLoading } = useAdminStats();
+
+ return (
+
+
Dashboard
+
+ {/* Stats Cards */}
+
+
+
+ Total Users
+
+
+
+ 1,234
+
+ +20% from last month
+
+
+
+
+
+
+ Active Users
+
+
+
+ 1,180
+
+ 95.6% of total
+
+
+
+
+
+
+ Organizations
+
+
+
+ 45
+
+ +5 this month
+
+
+
+
+
+ {/* Charts */}
+
+
+
+
+
+
+ );
+}
+```
+
+---
+
+## Conclusion
+
+These examples demonstrate:
+1. **Complete CRUD operations** (User Management)
+2. **Real-time data with polling** (Session Management)
+3. **Data visualization** (Admin Dashboard Charts)
+
+Each example follows the established patterns:
+- API hooks for data fetching
+- Reusable components
+- Proper error handling
+- Loading states
+- Type safety with TypeScript
+
+For more patterns and best practices, refer to:
+- **ARCHITECTURE.md**: System design
+- **CODING_STANDARDS.md**: Code style
+- **COMPONENT_GUIDE.md**: Component usage
+- **API_INTEGRATION.md**: API patterns
diff --git a/frontend/frontend-requirements.md b/frontend/frontend-requirements.md
new file mode 100644
index 0000000..0b7d41d
--- /dev/null
+++ b/frontend/frontend-requirements.md
@@ -0,0 +1,1933 @@
+# Frontend Requirements Document
+## Next.js + FastAPI Template Project
+
+---
+
+## 1. Project Overview
+
+This document specifies the requirements for a production-ready Next.js frontend template that integrates with a FastAPI backend. The template is designed to accelerate development of modern web applications with authentication, user management, and organization management capabilities.
+
+### 1.1 Purpose
+
+Provide a robust, scalable, and maintainable frontend foundation that:
+- Integrates seamlessly with the existing FastAPI backend
+- Follows modern React and Next.js best practices
+- Implements a clear and consistent architecture
+- Enables rapid feature development with minimal boilerplate
+- Serves as a reference implementation for team standards
+
+### 1.2 Scope
+
+The frontend encompasses:
+- User authentication and session management
+- User and organization administration interfaces
+- Reusable component library
+- API integration layer
+- State management infrastructure
+- Development utilities and tooling
+
+---
+
+## 2. Technology Stack
+
+### 2.1 Core Framework
+
+**Next.js (Latest Version)**
+- App Router architecture (not Pages Router)
+- Server Components by default, Client Components where interactivity is needed
+- TypeScript throughout the entire codebase
+- Strict mode enabled
+
+### 2.2 Styling
+
+**Tailwind CSS (Latest Version)**
+- Custom configuration for project-specific design tokens
+- Dark mode support (class-based strategy)
+- Responsive design utilities
+- Custom utilities as needed for common patterns
+
+**shadcn/ui (Latest)**
+- Component system built on Radix UI primitives
+- Customizable and accessible components
+- Components copied into project (not npm dependency)
+- Consistent with Tailwind configuration
+
+### 2.3 Data Fetching & State Management
+
+**TanStack Query (React Query v5)**
+- Server state management
+- Automatic background refetching
+- Cache management and invalidation
+- Optimistic updates for mutations
+- Request deduplication
+- Pagination and infinite query support
+
+**Zustand (Latest Version)**
+- Client-side application state (non-server state)
+- Authentication state
+- UI state (modals, sidebars, preferences)
+- Simple stores without excessive boilerplate
+- Minimal usage - prefer server state via TanStack Query
+
+### 2.4 Data Visualization
+
+**Recharts (Latest Version)**
+- Chart components for admin dashboards
+- Responsive charts
+- Customizable with Tailwind theme colors
+
+### 2.5 API Client Generation
+
+**OpenAPI TypeScript Codegen**
+- Generator: `openapi-typescript-codegen` (or `@hey-api/openapi-ts` as modern alternative)
+- Output: TypeScript types and Axios-based API client
+- Generation source: Backend OpenAPI spec endpoint
+- Two generation scripts:
+ 1. Frontend-local script (for frontend-only development)
+ 2. Root-level script (for monorepo/multi-module setups)
+
+### 2.6 HTTP Client
+
+**Axios (Latest Version)**
+- Used by generated API client
+- Interceptors for:
+ - Authentication token injection
+ - Error handling
+ - Request/response logging (dev mode)
+ - Token refresh logic
+
+### 2.7 Additional Libraries
+
+- **zod**: Runtime type validation and schema definition
+- **react-hook-form**: Form state management
+- **date-fns**: Date manipulation and formatting
+- **clsx** / **tailwind-merge**: Conditional class name handling
+- **lucide-react**: Icon system
+
+---
+
+## 3. Project Structure
+
+### 3.1 Directory Layout
+
+```
+frontend/
+├── src/
+│ ├── app/ # Next.js App Router
+│ │ ├── (auth)/ # Auth group layout
+│ │ │ ├── login/
+│ │ │ └── register/
+│ │ ├── (authenticated)/ # Protected routes group
+│ │ │ ├── admin/
+│ │ │ │ ├── layout.tsx
+│ │ │ │ ├── page.tsx
+│ │ │ │ ├── users/
+│ │ │ │ │ ├── page.tsx
+│ │ │ │ │ ├── [id]/
+│ │ │ │ │ │ └── page.tsx
+│ │ │ │ │ └── new/
+│ │ │ │ │ └── page.tsx
+│ │ │ │ └── organizations/
+│ │ │ │ ├── page.tsx
+│ │ │ │ ├── [id]/
+│ │ │ │ │ └── page.tsx
+│ │ │ │ └── new/
+│ │ │ │ └── page.tsx
+│ │ │ └── page.tsx # Authenticated home
+│ │ ├── dev/ # Development-only routes
+│ │ │ ├── components/
+│ │ │ │ └── page.tsx # Component showcase
+│ │ │ └── layout.tsx
+│ │ ├── layout.tsx # Root layout
+│ │ ├── page.tsx # Public home
+│ │ └── providers.tsx # Client-side providers
+│ ├── components/
+│ │ ├── ui/ # shadcn components
+│ │ │ ├── button.tsx
+│ │ │ ├── card.tsx
+│ │ │ ├── dialog.tsx
+│ │ │ ├── form.tsx
+│ │ │ ├── input.tsx
+│ │ │ ├── label.tsx
+│ │ │ ├── select.tsx
+│ │ │ ├── table.tsx
+│ │ │ ├── tabs.tsx
+│ │ │ ├── toast.tsx
+│ │ │ └── ... # Other core components
+│ │ ├── auth/ # Authentication components
+│ │ │ ├── LoginForm.tsx
+│ │ │ ├── RegisterForm.tsx
+│ │ │ ├── AuthGuard.tsx
+│ │ │ └── ProtectedRoute.tsx
+│ │ ├── admin/ # Admin-specific components
+│ │ │ ├── UserTable.tsx
+│ │ │ ├── UserForm.tsx
+│ │ │ ├── OrganizationTable.tsx
+│ │ │ ├── OrganizationForm.tsx
+│ │ │ ├── AdminSidebar.tsx
+│ │ │ └── AdminHeader.tsx
+│ │ ├── charts/ # Recharts wrappers
+│ │ │ ├── BarChartCard.tsx
+│ │ │ ├── LineChartCard.tsx
+│ │ │ └── PieChartCard.tsx
+│ │ ├── layout/ # Layout components
+│ │ │ ├── Header.tsx
+│ │ │ ├── Footer.tsx
+│ │ │ ├── Sidebar.tsx
+│ │ │ └── PageContainer.tsx
+│ │ ├── settings/ # Settings page components
+│ │ │ ├── ProfileSettings.tsx
+│ │ │ ├── PasswordSettings.tsx
+│ │ │ ├── SessionManagement.tsx
+│ │ │ ├── SessionCard.tsx
+│ │ │ └── PreferencesSettings.tsx
+│ │ └── common/ # Reusable common components
+│ │ ├── DataTable.tsx
+│ │ ├── LoadingSpinner.tsx
+│ │ ├── ErrorBoundary.tsx
+│ │ └── PageHeader.tsx
+│ ├── lib/
+│ │ ├── api/ # Generated API client
+│ │ │ ├── client.ts # Axios instance configuration
+│ │ │ ├── generated/ # Auto-generated code
+│ │ │ │ ├── index.ts
+│ │ │ │ ├── models/
+│ │ │ │ └── services/
+│ │ │ └── hooks/ # TanStack Query hooks
+│ │ │ ├── useAuth.ts
+│ │ │ ├── useUsers.ts
+│ │ │ ├── useOrganizations.ts
+│ │ │ └── useSessions.ts
+│ │ ├── auth/ # Authentication utilities
+│ │ │ ├── authClient.ts
+│ │ │ ├── tokens.ts
+│ │ │ └── session.ts
+│ │ ├── utils/ # Utility functions
+│ │ │ ├── cn.ts # Class name utility
+│ │ │ ├── formatters.ts
+│ │ │ ├── validators.ts
+│ │ │ └── errorUtils.ts # Error handling utilities
+│ │ ├── errors.ts # Error types and code mapping
+│ │ └── constants.ts # Application constants
+│ ├── services/ # Business logic services
+│ │ ├── authService.ts # Authentication operations
+│ │ ├── sessionService.ts # Session management
+│ │ └── adminService.ts # Admin-specific logic
+│ ├── hooks/ # Custom React hooks
+│ │ ├── useAuth.ts
+│ │ ├── useUser.ts
+│ │ ├── useMediaQuery.ts
+│ │ └── useDebounce.ts
+│ ├── stores/ # Zustand stores
+│ │ ├── authStore.ts
+│ │ ├── uiStore.ts
+│ │ └── index.ts
+│ ├── types/ # TypeScript types
+│ │ ├── auth.ts
+│ │ ├── user.ts
+│ │ ├── organization.ts
+│ │ └── common.ts
+│ ├── contexts/ # React contexts (if needed)
+│ │ └── index.ts
+│ ├── config/ # Configuration files
+│ │ ├── env.ts # Environment variables with validation
+│ │ ├── api.ts # API configuration
+│ │ └── queryClient.ts # TanStack Query configuration
+│ └── styles/
+│ └── globals.css # Global styles and Tailwind directives
+├── public/
+│ ├── images/
+│ └── icons/
+├── scripts/
+│ └── generate-api-client.sh # Frontend API generation script
+├── docs/
+│ ├── ARCHITECTURE.md # Architecture overview
+│ ├── CODING_STANDARDS.md # Coding standards
+│ ├── FEATURE_EXAMPLES.md # Feature implementation examples
+│ └── COMPONENT_GUIDE.md # Component usage guide
+├── .env.example
+├── .env.local
+├── next.config.js
+├── tailwind.config.ts
+├── tsconfig.json
+├── components.json # shadcn configuration
+└── package.json
+
+# Root level (multi-module project)
+root/
+├── scripts/
+│ └── generate-frontend-api.sh # Root-level API generation
+├── frontend/ # As above
+└── backend/ # FastAPI backend
+```
+
+### 3.2 File Naming Conventions
+
+- **Components**: PascalCase with `.tsx` extension (e.g., `UserTable.tsx`)
+- **Utilities**: camelCase with `.ts` extension (e.g., `formatDate.ts`)
+- **Hooks**: camelCase prefixed with `use` (e.g., `useAuth.ts`)
+- **Stores**: camelCase suffixed with `Store` (e.g., `authStore.ts`)
+- **Types**: camelCase with `.ts` extension (e.g., `user.ts`)
+- **Pages**: Next.js convention (`page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`)
+
+---
+
+## 4. Authentication & Authorization
+
+### 4.1 Authentication Flow
+
+**Requirements:**
+- Integration with FastAPI backend authentication endpoints
+- JWT-based authentication (access token + refresh token pattern)
+- Secure token storage strategy:
+ - **Access Token**: Stored in memory (React state) or sessionStorage (15-minute expiry)
+ - **Refresh Token**: Stored in httpOnly cookie (preferred) or secure localStorage with encryption (7-day expiry)
+ - All API requests include: `Authorization: Bearer {access_token}` header
+- Automatic token refresh before expiration
+- Session persistence across browser reloads
+- Clear session expiration handling
+- Per-device session tracking with backend
+
+**Login Flow:**
+1. User submits credentials via `LoginForm`
+2. API client calls backend `/api/v1/auth/login` endpoint
+3. Backend returns access token and refresh token
+4. Backend creates session record with device information
+5. Access token stored in memory/sessionStorage (short-lived, 15 minutes)
+6. Refresh token stored in httpOnly cookie or secure localStorage (long-lived, 7 days)
+7. Auth store updated with user information
+8. Redirect to intended destination or home
+9. Axios interceptor adds `Authorization: Bearer {accessToken}` to all requests
+
+**Token Refresh Flow:**
+1. Axios interceptor detects 401 response
+2. Attempts token refresh via `/api/v1/auth/refresh` endpoint with refresh token
+3. Backend validates refresh token JTI (JWT ID) against active session in database
+4. If session valid, backend generates NEW access token and NEW refresh token (token rotation)
+5. Backend updates session with new JTI and expiration timestamp
+6. Frontend stores new tokens and retries original request
+7. Old refresh token is invalidated (cannot be reused)
+
+**Logout Flow:**
+1. User initiates logout
+2. API client calls backend `/api/v1/auth/logout` endpoint with refresh token
+3. Backend deactivates the specific session (device) using the refresh token's JTI
+4. Other devices remain logged in (per-device session management)
+5. Clear all tokens from storage (memory, sessionStorage, localStorage, cookies)
+6. Clear auth store
+7. Clear TanStack Query cache
+8. Redirect to login or home page
+
+**Logout All Devices Flow:**
+1. User selects "Logout All Devices" (from session management or security page)
+2. API client calls backend `/api/v1/auth/logout-all` endpoint
+3. Backend deactivates all sessions for the current user
+4. Clear local tokens and state
+5. Redirect to login page
+
+### 4.2 Protected Routes
+
+**Route Guard Implementation:**
+- Middleware or layout-based protection for authenticated routes
+- Server-side session validation where possible
+- Client-side auth state checks for immediate UI updates
+- Graceful handling of unauthenticated access (redirect to login with return URL)
+
+**Permission Levels:**
+- Public routes: accessible to all (home, login, register)
+- Authenticated routes: require valid session
+- Admin routes: require authenticated user with admin role
+- Organization routes: require membership in organization
+
+### 4.3 Auth Components
+
+**LoginForm**
+- Username/email and password fields
+- Form validation with react-hook-form and zod
+- Error handling with user-friendly messages
+- Loading states during submission
+- "Remember me" option (if applicable)
+- Link to registration and password reset
+
+**RegisterForm**
+- User registration fields (as required by backend)
+- Client-side validation matching backend requirements
+- Terms of service acceptance
+- Email verification flow (if applicable)
+
+**AuthGuard**
+- HOC or component for protecting routes
+- Handles loading state during auth check
+- Redirects if unauthorized
+- Passes through if authorized
+
+### 4.3 Password Reset Flow
+
+**Password Reset Request:**
+1. User provides email on reset form
+2. API client calls `/api/v1/auth/password-reset/request` with email
+3. Backend sends email with reset token (if email exists)
+4. Backend always returns success to prevent email enumeration attacks
+5. Frontend displays message: "If your email is registered, you'll receive a reset link"
+6. User receives email with password reset link containing token parameter
+
+**Password Reset Confirmation:**
+1. User clicks email link with token parameter (e.g., `/password-reset/confirm?token=...`)
+2. Frontend validates token parameter is present
+3. User enters new password (with confirmation)
+4. Client-side validation: minimum 8 characters, 1 digit, 1 uppercase letter
+5. API client calls `/api/v1/auth/password-reset/confirm` with token and new password
+6. Backend validates token, checks expiration, updates password
+7. Redirect to login with success message
+8. User can now login with new password
+
+**Password Change (Authenticated Users):**
+1. User navigates to password settings page
+2. User provides current password and new password
+3. API client calls `/api/v1/users/me/password` with current and new passwords
+4. Backend verifies current password, validates new password, updates password hash
+5. Show success message
+6. Optional: Logout all other devices for security
+
+### 4.4 Auth State Management
+
+**Zustand Store Requirements:**
+```typescript
+interface AuthStore {
+ // State
+ user: User | null;
+ accessToken: string | null;
+ refreshToken: string | null;
+ isAuthenticated: boolean;
+ isLoading: boolean;
+
+ // Authentication actions
+ login: (credentials: LoginCredentials) => Promise;
+ logout: () => Promise; // Logout current device
+ logoutAll: () => Promise; // Logout all devices
+ refreshTokens: () => Promise; // Refresh access token
+ checkAuth: () => Promise; // Verify current session
+
+ // Token management
+ setTokens: (accessToken: string, refreshToken: string) => void;
+ clearAuth: () => void; // Clear all auth state
+}
+```
+
+**TanStack Query Integration:**
+- `useAuth` hook wrapping auth operations
+- Automatic user data refetching on window focus
+- Cache invalidation on logout
+- Optimistic updates where appropriate
+
+### 4.5 Session Management
+
+The backend implements comprehensive per-device session tracking. Users can view active sessions across all devices and manage them individually.
+
+**Session Data Model:**
+```typescript
+interface UserSession {
+ id: UUID; // Session identifier
+ device_name: string | null; // "iPhone 14", "Chrome on MacBook"
+ device_id: string | null; // Persistent device identifier
+ ip_address: string | null; // Last known IP address
+ location_city: string | null; // Geolocation city
+ location_country: string | null; // Geolocation country
+ last_used_at: datetime; // Last activity timestamp
+ created_at: datetime; // Session creation time
+ expires_at: datetime; // Session expiration time
+ is_current: boolean; // Is this the current session?
+}
+```
+
+**Session Management UI Requirements:**
+
+**Session List Page** (`/settings/sessions`):
+- Display all active sessions for the current user
+- Show device name, location, last used time, and created date
+- Highlight the current session with "This device" or "Current session" badge
+- Action button to revoke each non-current session
+- "Logout All Other Devices" button at the top
+- Confirm before revoking sessions
+- Auto-refresh session list periodically
+
+**Session Information Display:**
+- Device icon based on device type (desktop, mobile, tablet)
+- Location display: "San Francisco, United States" (if available)
+- Time display: "Last used 2 hours ago" (relative time with date-fns)
+- Expiration display: "Expires in 6 days"
+- "This device" badge for current session (different style, cannot revoke)
+
+**Session API Integration:**
+- `GET /api/v1/sessions/me` - List all active sessions with pagination
+- `DELETE /api/v1/sessions/{session_id}` - Revoke specific session (not current)
+- `POST /api/v1/auth/logout` - Logout current device
+- `POST /api/v1/auth/logout-all` - Logout all devices
+- `DELETE /api/v1/sessions/me/expired` - Cleanup expired sessions (optional, admin-only)
+
+**Component Requirements:**
+- `SessionList.tsx` - Display active sessions table or card grid
+- `SessionCard.tsx` - Individual session display with device info
+- `RevokeSessionDialog.tsx` - Confirmation dialog before revoking
+- Integration with settings layout
+- Empty state: "No other active sessions"
+
+**User Experience Considerations:**
+- Prevent revoking the current session via the session list (only via logout button)
+- Show loading state when revoking sessions
+- Show success toast: "Session revoked successfully"
+- Update session list immediately after revoking
+- Warn before "Logout All Other Devices": "This will log you out of all other devices"
+- Consider security notifications: "New login from Unknown Device in New York, USA"
+
+---
+
+## 5. API Integration
+
+### 5.1 OpenAPI Client Generation
+
+**Generation Scripts:**
+
+**Frontend Script** (`frontend/scripts/generate-api-client.sh`):
+- Fetches OpenAPI spec from backend at `/api/v1/openapi.json`
+ - Development: `http://localhost:8000/api/v1/openapi.json`
+ - Docker: `http://backend:8000/api/v1/openapi.json`
+- Generates TypeScript client in `src/lib/api/generated/`
+- Runs as npm script: `npm run generate:api`
+- Can be run independently for frontend-only development
+
+**Root Script** (`root/scripts/generate-frontend-api.sh`):
+- Orchestrates generation for multi-module setup
+- Ensures backend is available (or uses spec file)
+- Navigates to frontend directory and runs generation
+- Useful for CI/CD and monorepo workflows
+
+**Generator Configuration:**
+- Tool: `@hey-api/openapi-ts` (modern, actively maintained)
+- Output language: TypeScript
+- HTTP client: Axios
+- Generate client services: Yes
+- Generate models: Yes
+- Generate request bodies: Yes
+- Export schemas: Yes
+- Use union types: Yes
+- Generate hooks: Optional (we'll create custom React Query hooks)
+
+### 5.2 Axios Client Configuration
+
+**Requirements:**
+
+```typescript
+// src/lib/api/client.ts
+- Base Axios instance with configured baseURL
+- Request interceptor for adding auth tokens
+- Response interceptor for error handling
+- Request interceptor for logging (dev mode only)
+- Timeout configuration
+- Retry logic for transient failures
+- Support for request cancellation
+```
+
+**Interceptor Responsibilities:**
+- **Request Interceptor:**
+ - Add `Authorization: Bearer {token}` header
+ - Add common headers (Content-Type, etc.)
+ - Log requests in development
+
+- **Response Interceptor:**
+ - Handle 401 errors (trigger token refresh)
+ - Handle 403 errors (insufficient permissions)
+ - Handle 500 errors (show user-friendly message)
+ - Handle network errors
+ - Log responses in development
+
+**Error Response Handling:**
+
+The backend returns structured error responses that must be properly parsed:
+
+```typescript
+// Backend error response format
+interface APIErrorResponse {
+ success: false;
+ errors: Array<{
+ code: string; // e.g., "AUTH_001", "USER_002", "VAL_001"
+ message: string; // Human-readable error message
+ field?: string; // Field that caused the error (for form validation)
+ }>;
+}
+```
+
+**Error Handling Requirements:**
+- Extract error messages from `errors` array
+- Display field-specific errors in forms (match `field` property to form fields)
+- Map error codes to user-friendly messages (create error code dictionary)
+- Handle specific HTTP status codes:
+ - **401 Unauthorized**: Trigger token refresh, then retry request
+ - **403 Forbidden**: Show "You don't have permission" message
+ - **429 Too Many Requests**: Show "Please slow down" with retry time
+ - **500 Internal Server Error**: Show generic error, log details for debugging
+ - **Network errors**: Show "Check your internet connection" message
+- Log full error details to console in development mode (never in production)
+- Never expose sensitive error details to users (stack traces, internal paths, etc.)
+
+**Error Code Mapping Example:**
+```typescript
+const ERROR_MESSAGES: Record = {
+ 'AUTH_001': 'Invalid email or password',
+ 'USER_002': 'This email is already registered',
+ 'USER_003': 'User not found',
+ 'VAL_001': 'Please check your input',
+ 'ORG_001': 'Organization name already exists',
+ // ... map all backend error codes
+};
+```
+
+### 5.3 TanStack Query Integration
+
+**Query Configuration** (`src/config/queryClient.ts`):
+```typescript
+- Default staleTime: 60000 (1 minute)
+- Default cacheTime: 300000 (5 minutes)
+- Retry logic: 3 attempts with exponential backoff
+- RefetchOnWindowFocus: true (for data freshness)
+- RefetchOnReconnect: true
+- Error handling defaults
+```
+
+**Query Hooks Pattern:**
+
+Each API endpoint should have corresponding hooks in `src/lib/api/hooks/`:
+
+```typescript
+// Example: useUsers.ts
+export function useUsers(filters?: UserFilters) {
+ return useQuery({
+ queryKey: ['users', filters],
+ queryFn: () => apiClient.users.getUsers(filters),
+ });
+}
+
+export function useUser(userId: string) {
+ return useQuery({
+ queryKey: ['users', userId],
+ queryFn: () => apiClient.users.getUser(userId),
+ enabled: !!userId,
+ });
+}
+
+export function useCreateUser() {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: (data: CreateUserDto) => apiClient.users.createUser(data),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ },
+ });
+}
+
+export function useUpdateUser() {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: ({ id, data }: { id: string; data: UpdateUserDto }) =>
+ apiClient.users.updateUser(id, data),
+ onSuccess: (_, { id }) => {
+ queryClient.invalidateQueries({ queryKey: ['users', id] });
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ },
+ });
+}
+
+export function useDeleteUser() {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: (userId: string) => apiClient.users.deleteUser(userId),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['users'] });
+ },
+ });
+}
+```
+
+**Hook Organization:**
+- One file per resource/entity (users, organizations, etc.)
+- Query hooks for GET operations
+- Mutation hooks for POST/PUT/PATCH/DELETE operations
+- Consistent naming: `use[Resource]`, `use[Resource]s`, `useCreate[Resource]`, etc.
+- Proper query key structure for cache invalidation
+- Optimistic updates for better UX where appropriate
+
+---
+
+## 6. State Management Architecture
+
+### 6.1 State Management Philosophy
+
+**Pragmatic Approach:**
+- Use TanStack Query for all server state (primary state management)
+- Use Zustand sparingly for client-only state
+- Avoid prop drilling with minimal context providers
+- Keep state as local as possible
+- Lift state only when necessary
+
+**State Categories:**
+
+1. **Server State** (TanStack Query):
+ - User data
+ - Organization data
+ - Session data (list of active sessions)
+ - Any data fetched from API
+ - Managed through query hooks
+
+2. **Auth State** (Zustand):
+ - Current user
+ - Authentication status
+ - Token management (access token, refresh token)
+ - Token refresh logic
+
+3. **UI State** (Zustand):
+ - Sidebar open/closed
+ - Theme preference
+ - Active modals
+ - Toast notifications
+
+4. **Form State** (react-hook-form):
+ - Form values
+ - Validation errors
+ - Submit status
+
+5. **Local Component State** (useState):
+ - UI toggles
+ - Temporary input values
+ - Component-specific flags
+
+### 6.2 Zustand Stores
+
+**Auth Store** (`src/stores/authStore.ts`):
+```typescript
+interface AuthStore {
+ user: User | null;
+ isAuthenticated: boolean;
+ isLoading: boolean;
+ setUser: (user: User | null) => void;
+ clearAuth: () => void;
+}
+```
+
+**UI Store** (`src/stores/uiStore.ts`):
+```typescript
+interface UIStore {
+ sidebarOpen: boolean;
+ theme: 'light' | 'dark' | 'system';
+ setSidebarOpen: (open: boolean) => void;
+ toggleSidebar: () => void;
+ setTheme: (theme: 'light' | 'dark' | 'system') => void;
+}
+```
+
+**Store Guidelines:**
+- Keep stores small and focused
+- Avoid duplicating server state
+- Use selectors for computed values
+- Persist where appropriate (localStorage)
+- Document why Zustand is chosen over alternatives for each store
+
+### 6.3 Context Providers (Minimal Usage)
+
+**When to Use Contexts:**
+- Wrapping app with TanStack Query provider
+- Theme provider (if not using Zustand)
+- Providing deeply nested utilities (rare)
+
+**When NOT to Use Contexts:**
+- Server state (use TanStack Query)
+- Auth state (use Zustand)
+- Component props that can be passed directly
+
+### 6.4 Custom Hooks
+
+**Custom Hook Requirements:**
+- Abstract common patterns
+- Compose other hooks when needed
+- Return consistent interfaces
+- Handle loading and error states
+- Include proper TypeScript types
+
+**Example Custom Hooks:**
+- `useAuth()`: Wraps auth store and operations
+- `useUser()`: Gets current user with loading state
+- `useDebounce()`: Debounce input values
+- `useMediaQuery()`: Responsive breakpoint detection
+- `usePermissions()`: Check user permissions
+
+---
+
+## 7. UI Components
+
+### 7.1 shadcn/ui Components
+
+**Core Components Required:**
+- Button
+- Card
+- Dialog / Modal
+- Form components (Input, Label, Select, Textarea, Checkbox, Radio)
+- Table
+- Tabs
+- Toast / Notification
+- Dropdown Menu
+- Popover
+- Sheet (Sidebar)
+- Avatar
+- Badge
+- Separator
+- Skeleton (loading states)
+- Alert
+- Command (search/command palette)
+- Progress
+
+**Admin Components:**
+- DataTable (enhanced table with sorting, filtering, pagination)
+- Calendar
+- Date Picker
+- Multi-select
+
+**Installation:**
+- Install via shadcn CLI: `npx shadcn-ui@latest add [component]`
+- Customize theme in `tailwind.config.ts`
+- Document customizations in `COMPONENT_GUIDE.md`
+
+### 7.2 Custom Components
+
+**Layout Components** (`src/components/layout/`):
+
+**Header.tsx**
+- App logo/title
+- Navigation links
+- User menu dropdown
+- Theme toggle
+- Mobile menu button
+
+**Footer.tsx**
+- Copyright information
+- Links to docs, support
+- Social media links (if applicable)
+
+**Sidebar.tsx**
+- Navigation menu for authenticated users
+- Collapsible sections
+- Active route highlighting
+- Responsive (drawer on mobile)
+
+**PageContainer.tsx**
+- Consistent page padding
+- Max-width container
+- Responsive layout
+
+**Admin Components** (`src/components/admin/`):
+
+**UserTable.tsx**
+- Display users in data table
+- Sortable columns: name, email, role, created date
+- Filterable by role, status
+- Searchable by name/email
+- Actions: edit, delete, impersonate (if applicable)
+- Pagination
+- Row selection for bulk operations
+
+**UserForm.tsx**
+- Create/edit user form
+- Fields: name, email, role, status, organization assignment
+- Validation with react-hook-form + zod
+- Submit and cancel actions
+- Loading and error states
+
+**OrganizationTable.tsx**
+- Display organizations in data table
+- Sortable columns: name, member count, created date
+- Searchable by name
+- Actions: edit, delete, view members
+- Pagination
+
+**OrganizationForm.tsx**
+- Create/edit organization form
+- Fields: name, description, settings
+- Validation
+- Submit and cancel actions
+
+**AdminSidebar.tsx**
+- Admin navigation menu
+- Links to user management, org management, settings
+- Collapsible sections
+- Active route indication
+
+**AdminHeader.tsx**
+- Admin page title
+- Breadcrumbs
+- Action buttons (contextual)
+
+**AdminStats.tsx**
+- Dashboard statistics cards
+- Display total users, active users, total organizations
+- Growth indicators (percentage change)
+- Optional chart integration (mini sparklines)
+- Responsive card grid
+
+**BulkActionBar.tsx**
+- Appears when rows are selected in admin tables
+- Selection count display ("3 users selected")
+- Action dropdown (Activate, Deactivate, Delete)
+- Confirmation dialog before destructive actions
+- Progress indicator for bulk operations
+- Clear selection button
+
+**UserActivationToggle.tsx**
+- Toggle or button to activate/deactivate individual users
+- Show current status (Active/Inactive)
+- Confirmation for deactivation
+- Admin-only component (permission check)
+- Optimistic UI updates
+
+**OrganizationMemberManager.tsx**
+- Add members to organization (user search/select)
+- Remove members from organization
+- Change member roles (owner, admin, member)
+- Display member list with roles
+- Role badge styling
+- Permission checks (who can manage members)
+
+**Chart Components** (`src/components/charts/`):
+
+**BarChartCard.tsx**
+- Wrapped Recharts BarChart
+- Card container with title and description
+- Responsive
+- Themed colors
+
+**LineChartCard.tsx**
+- Wrapped Recharts LineChart
+- Similar structure to BarChartCard
+
+**PieChartCard.tsx**
+- Wrapped Recharts PieChart
+- Legend
+- Tooltips
+
+**Settings Components** (`src/components/settings/`):
+
+**ProfileSettings.tsx**
+- User profile edit form
+- Fields: first_name, last_name, email, phone_number
+- Avatar upload (optional)
+- Preferences JSON editor (optional)
+- Form validation and submission
+
+**PasswordSettings.tsx**
+- Password change form
+- Fields: current password, new password, confirm new password
+- Password strength indicator
+- Validation: min 8 chars, 1 digit, 1 uppercase
+- Option to logout all other devices after change
+
+**SessionManagement.tsx**
+- List all active sessions
+- Display session cards with device info
+- Revoke session functionality
+- "Logout All Other Devices" button
+- Current session highlighting
+
+**SessionCard.tsx**
+- Individual session display
+- Device icon (desktop, mobile, tablet)
+- Location and IP display
+- Last used timestamp (relative time)
+- Revoke button (disabled for current session)
+
+**PreferencesSettings.tsx**
+- User preferences form (theme, notifications, etc.)
+- Stored in User.preferences JSON field
+- Theme toggle (light, dark, system)
+- Optional email notification settings
+
+**Common Components** (`src/components/common/`):
+
+**DataTable.tsx**
+- Generic reusable data table
+- Props: data, columns, pagination, sorting, filtering
+- Built on shadcn Table component
+- TypeScript generic for type safety
+
+**LoadingSpinner.tsx**
+- Centered spinner
+- Size variants
+- Accessible (aria-label)
+
+**ErrorBoundary.tsx**
+- React error boundary
+- Display fallback UI on errors
+- Error reporting hook
+
+**PageHeader.tsx**
+- Page title
+- Optional description
+- Optional action buttons
+
+### 7.3 Component Guidelines
+
+**Component Structure:**
+```typescript
+// Imports
+import { ... } from 'react';
+import { ... } from 'external-lib';
+import { ... } from '@/components/ui';
+import { ... } from '@/lib';
+
+// Types
+interface ComponentProps {
+ // ...
+}
+
+// Component
+export function ComponentName({ prop1, prop2 }: ComponentProps) {
+ // Hooks
+ // Derived state
+ // Event handlers
+
+ // Render
+ return (
+ // JSX
+ );
+}
+```
+
+**Best Practices:**
+- Prefer named exports over default exports
+- Co-locate types with component file
+- Use TypeScript for all props
+- Destructure props in function signature
+- Keep components focused (single responsibility)
+- Extract reusable logic to hooks
+- Use composition over prop drilling
+- Implement proper loading and error states
+- Make components accessible (ARIA labels, keyboard navigation)
+
+---
+
+## 8. Routing & Pages
+
+### 8.1 Route Structure
+
+**Public Routes:**
+- `/` - Home page (accessible to all)
+- `/login` - Login page
+- `/register` - Registration page
+
+**Authenticated Routes:**
+- `/` - Home page (authenticated view, different from public)
+- `/dashboard` - Optional: user dashboard
+
+**Admin Routes:**
+- `/admin` - Admin dashboard/landing with statistics and charts
+- `/admin/users` - User list with search, filters, and bulk actions
+- `/admin/users/[id]` - User detail/edit with sessions and organizations
+- `/admin/users/new` - Create user (can set superuser status)
+- `/admin/organizations` - Organization list with search and filters
+- `/admin/organizations/[id]` - Organization detail/edit with settings
+- `/admin/organizations/[id]/members` - Organization member management
+- `/admin/organizations/new` - Create organization
+
+**Account/Settings Routes:**
+- `/settings` - Settings layout (redirects to /settings/profile)
+- `/settings/profile` - User profile edit (first_name, last_name, email, phone, preferences)
+- `/settings/password` - Change password (current + new password)
+- `/settings/sessions` - View and manage active sessions across devices
+- `/settings/preferences` - User preferences (theme, notifications, etc.)
+
+**Development Routes (dev environment only):**
+- `/dev/components` - Component showcase/storybook
+- `/dev/icons` - Icon preview
+- `/dev/theme` - Theme preview
+
+### 8.2 Page Specifications
+
+**Home Page** (`/`):
+
+**Public View:**
+- Hero section with project description
+- Feature highlights
+- Call-to-action (login/register buttons)
+- Example components showcasing capabilities
+- Footer
+
+**Authenticated View:**
+- Welcome message with user name
+- Quick stats or dashboard widgets
+- Recent activity
+- Navigation to key areas (admin, profile)
+
+**Admin Landing** (`/admin`):
+
+- Overview dashboard
+- Key metrics cards (total users, total organizations, active sessions)
+- Charts showing trends (user growth, organization growth)
+- Quick links to management sections
+- Recent activity log
+
+**User Management** (`/admin/users`):
+
+- User table with all features (search, sort, filter, paginate)
+- "Create User" button
+- Bulk actions (if applicable)
+- Export functionality (optional)
+
+**User Detail** (`/admin/users/[id]`):
+
+- User information display
+- Edit form
+- Organization memberships
+- Activity log
+- Danger zone (delete user)
+
+**User Creation** (`/admin/users/new`):
+
+- User creation form
+- Form validation
+- Success redirect to user list or detail
+
+**Organization Management** (`/admin/organizations`):
+
+- Organization table with all features
+- "Create Organization" button
+- Bulk actions (if applicable)
+
+**Organization Detail** (`/admin/organizations/[id]`):
+
+- Organization information display
+- Edit form
+- Member list
+- Settings
+- Danger zone (delete organization)
+
+**Organization Creation** (`/admin/organizations/new`):
+
+- Organization creation form
+- Form validation
+- Success redirect
+
+**Component Showcase** (`/dev/components`):
+
+- Grid or list of all reusable components
+- Each component shown in various states (default, loading, error, disabled)
+- Interactive controls to test component props
+- Code snippets showing usage
+- Only accessible in development environment
+
+### 8.3 Layout Strategy
+
+**Root Layout** (`src/app/layout.tsx`):
+- HTML structure
+- TanStack Query provider
+- Theme provider
+- Toast provider
+- Global metadata
+
+**Auth Group Layout** (`src/app/(auth)/layout.tsx`):
+- Centered form layout
+- No header/footer
+- Background styling
+
+**Authenticated Group Layout** (`src/app/(authenticated)/layout.tsx`):
+- Header
+- Optional sidebar
+- Main content area
+- Footer
+- Auth guard
+
+**Admin Layout** (`src/app/(authenticated)/admin/layout.tsx`):
+- Admin header
+- Admin sidebar
+- Breadcrumbs
+- Admin-specific auth guard (role check)
+
+**Dev Layout** (`src/app/dev/layout.tsx`):
+- Simple layout
+- Environment check (only render in dev)
+- Navigation between dev pages
+
+### 8.4 Page Components
+
+**Structure:**
+- Each page is a Server Component by default
+- Client Components used for interactivity
+- Loading states via `loading.tsx`
+- Error handling via `error.tsx`
+- Metadata exported for SEO
+
+**Example:**
+```typescript
+// src/app/(authenticated)/admin/users/page.tsx
+import { Metadata } from 'next';
+import { UserTable } from '@/components/admin/UserTable';
+
+export const metadata: Metadata = {
+ title: 'User Management',
+ description: 'Manage application users',
+};
+
+export default function UsersPage() {
+ return (
+
+ );
+}
+```
+
+---
+
+## 9. Development Environment
+
+### 9.1 Environment Variables
+
+**Required Environment Variables:**
+```env
+# API Configuration
+NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
+NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
+NEXT_PUBLIC_API_TIMEOUT=30000
+
+# Authentication
+NEXT_PUBLIC_TOKEN_REFRESH_THRESHOLD=300000 # 5 minutes in ms (refresh before expiry)
+NEXT_PUBLIC_ACCESS_TOKEN_EXPIRY=900000 # 15 minutes in ms
+NEXT_PUBLIC_REFRESH_TOKEN_EXPIRY=604800000 # 7 days in ms
+
+# App Configuration
+NEXT_PUBLIC_APP_NAME=Template Project
+NEXT_PUBLIC_APP_URL=http://localhost:3000
+
+# Feature Flags
+NEXT_PUBLIC_ENABLE_REGISTRATION=true
+NEXT_PUBLIC_ENABLE_SESSION_MANAGEMENT=true
+
+# Development
+NODE_ENV=development
+
+# Optional: Debugging
+NEXT_PUBLIC_DEBUG_API=false
+```
+
+**Environment File Structure:**
+- `.env.example` - Template with all variables (committed)
+- `.env.local` - Local overrides (gitignored)
+- `.env.development` - Development defaults (optional)
+- `.env.production` - Production values (optional, for reference)
+
+**Environment Validation:**
+- Use zod to validate environment variables at build time
+- Fail fast if required variables are missing
+- Type-safe access via `src/config/env.ts`
+
+### 9.2 Development Scripts
+
+**package.json Scripts:**
+```json
+{
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "lint:fix": "next lint --fix",
+ "type-check": "tsc --noEmit",
+ "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
+ "generate:api": "./scripts/generate-api-client.sh",
+ "test": "jest",
+ "test:watch": "jest --watch"
+ }
+}
+```
+
+### 9.3 Code Quality Tools
+
+**ESLint:**
+- Next.js ESLint configuration
+- TypeScript ESLint rules
+- React hooks rules
+- Import order rules
+- Accessibility rules (eslint-plugin-jsx-a11y)
+
+**Prettier:**
+- Consistent code formatting
+- Integrated with ESLint
+- Pre-commit hook (optional: husky + lint-staged)
+
+**TypeScript:**
+- Strict mode enabled
+- Path aliases configured (`@/*` -> `src/*`)
+- Incremental compilation
+- No implicit any
+
+### 9.4 Development Routes Requirements
+
+**Environment Check:**
+- `/dev/*` routes only accessible when `NODE_ENV === 'development'`
+- Display 404 or redirect in production
+
+**Component Showcase Page:**
+- Organized by category (UI, Admin, Layout, Common, Charts)
+- Each component in isolated container
+- Interactive props (where applicable)
+- Copy code snippet button
+- Search/filter components
+- Dark mode toggle to preview components in both themes
+
+---
+
+## 10. Code Standards & Conventions
+
+### 10.1 TypeScript Standards
+
+**Type Definitions:**
+- Define types in `src/types/` for shared types
+- Co-locate types with components for component-specific types
+- Use interfaces for object shapes, types for unions/primitives
+- Avoid `any` - use `unknown` if type is truly unknown
+- Use generic types for reusable components and utilities
+
+**Naming:**
+- Interfaces: PascalCase with descriptive names (e.g., `UserProfile`, `ApiResponse`)
+- Type aliases: PascalCase (e.g., `UserId`, `DateString`)
+- Enums: PascalCase for enum name, UPPER_SNAKE_CASE for values
+
+**Import Aliases:**
+- `@/` alias maps to `src/`
+- Use `@/components/ui` instead of relative paths for UI components
+- Use `@/lib` for library code
+- Use `@/types` for shared types
+
+### 10.2 Component Standards
+
+**Naming:**
+- PascalCase for component files and component names
+- Match file name with component name
+
+**Structure:**
+- One component per file
+- Extract complex logic into custom hooks
+- Separate concerns (presentation vs. logic)
+
+**Props:**
+- Define explicit prop interfaces
+- Use destructuring in function signature
+- Provide defaults via destructuring when appropriate
+- Document complex props with JSDoc comments
+
+**State:**
+- Keep state as local as possible
+- Use appropriate state management for each use case
+- Avoid redundant state (derive when possible)
+
+### 10.3 Styling Standards
+
+**Tailwind Usage:**
+- Use Tailwind utility classes directly in JSX
+- Avoid inline styles unless absolutely necessary
+- Use `cn()` utility for conditional classes
+- Extract repeated class combinations into components
+
+**Responsive Design:**
+- Mobile-first approach
+- Use Tailwind responsive modifiers (sm, md, lg, xl, 2xl)
+- Test on multiple screen sizes
+
+**Dark Mode:**
+- Use Tailwind dark mode classes (dark:*)
+- Ensure all components support dark mode
+- Test both light and dark themes
+
+### 10.4 API Integration Standards
+
+**Query Hooks:**
+- One hook per operation
+- Consistent naming: `use[Resource]`, `use[Resource]s`, `useCreate[Resource]`, etc.
+- Proper query keys for cache management
+- Handle loading, error, and success states
+
+**Mutation Hooks:**
+- Return mutation function and status
+- Invalidate relevant queries on success
+- Handle errors gracefully
+- Provide user feedback (toast notifications)
+
+**Error Handling:**
+- Display user-friendly error messages
+- Log errors to console (or error service)
+- Show retry options when appropriate
+- Avoid exposing technical details to users
+
+### 10.5 Form Standards
+
+**Form Implementation:**
+- Use react-hook-form for form state
+- Use zod for validation schemas
+- Use shadcn Form components for consistent UI
+- Provide immediate validation feedback
+- Disable submit button during submission
+- Show loading state during submission
+
+**Form Structure:**
+```typescript
+// Define schema
+const formSchema = z.object({
+ // fields
+});
+
+// Use hook
+const form = useForm({
+ resolver: zodResolver(formSchema),
+ defaultValues: {
+ // defaults
+ },
+});
+
+// Submit handler
+const onSubmit = async (data: z.infer) => {
+ // mutation logic
+};
+```
+
+### 10.6 Testing Standards (Future)
+
+**Test Structure:**
+- Unit tests for utilities and hooks
+- Integration tests for API hooks
+- Component tests for reusable components
+- E2E tests for critical user flows
+
+**Testing Tools:**
+- Jest for unit tests
+- React Testing Library for component tests
+- Playwright or Cypress for E2E tests (optional)
+
+---
+
+## 11. Documentation Requirements
+
+### 11.1 Architecture Documentation
+
+**ARCHITECTURE.md Requirements:**
+
+**System Overview:**
+- High-level architecture diagram
+- Explanation of chosen technologies and why
+- Data flow diagrams (authentication, API calls, state management)
+- Folder structure rationale
+
+**Key Concepts:**
+- App Router vs. Pages Router decision
+- Server Components vs. Client Components usage
+- State management philosophy
+- API integration approach
+
+**Architecture Decisions:**
+- Why TanStack Query over alternatives
+- Why Zustand over alternatives
+- OpenAPI client generation rationale
+- Authentication strategy explanation
+
+### 11.2 Coding Standards Documentation
+
+**CODING_STANDARDS.md Requirements:**
+
+**TypeScript Guidelines:**
+- Type definition best practices
+- When to use interfaces vs. types
+- How to handle unknown types
+- Generic type usage
+
+**Component Guidelines:**
+- Component structure template
+- Prop definition standards
+- State management in components
+- Hook usage patterns
+
+**Styling Guidelines:**
+- Tailwind usage patterns
+- Responsive design approach
+- Dark mode implementation
+- Component styling dos and don'ts
+
+**API Integration Guidelines:**
+- How to create query hooks
+- How to create mutation hooks
+- Error handling patterns
+- Cache invalidation strategies
+
+**Form Guidelines:**
+- react-hook-form setup
+- Validation with zod
+- Error display
+- Submit handling
+
+### 11.3 Feature Implementation Examples
+
+**FEATURE_EXAMPLES.md Requirements:**
+
+Provide 2-3 complete feature implementation walkthroughs, including:
+
+**Example 1: User Management Feature**
+- Backend API endpoints used
+- Generated API client usage
+- Query hooks creation (`src/lib/api/hooks/useUsers.ts`)
+- Component implementation (`src/components/admin/UserTable.tsx`)
+- Page implementation (`src/app/(authenticated)/admin/users/page.tsx`)
+- Form implementation (`src/components/admin/UserForm.tsx`)
+- Complete code snippets for each file
+
+**Example 2: Organization Management Feature**
+- Similar structure to Example 1
+- Highlights differences and patterns
+
+**Example 3: Adding a New Chart to Admin Dashboard**
+- Data fetching setup
+- Chart component creation
+- Integration into dashboard page
+- Styling and responsiveness
+
+**Each Example Should Show:**
+1. What files to create/modify
+2. Where each file goes in the project structure
+3. Complete, working code for each file
+4. How files interact with each other
+5. Testing the feature (manual testing steps)
+
+### 11.4 Component Usage Guide
+
+**COMPONENT_GUIDE.md Requirements:**
+
+**shadcn/ui Components:**
+- List of installed components
+- Usage examples for each
+- Customization examples
+- Common patterns (forms, dialogs, tables)
+
+**Custom Components:**
+- Purpose and when to use
+- Props documentation
+- Usage examples
+- Styling and customization
+
+**Component Composition:**
+- How to compose components together
+- Common patterns (Card + Table, Dialog + Form)
+- Best practices for component composition
+
+---
+
+## 12. Non-Functional Requirements
+
+### 12.1 Performance
+
+**Target Metrics:**
+- First Contentful Paint: < 1.5s
+- Time to Interactive: < 3s
+- Lighthouse Performance Score: > 90
+
+**Optimization Strategies:**
+- Image optimization (next/image)
+- Code splitting and lazy loading
+- Minimize client-side JavaScript
+- Efficient bundle size (monitor with Bundle Analyzer)
+- Proper caching strategies
+
+### 12.2 Accessibility
+
+**Standards:**
+- WCAG 2.1 Level AA compliance
+- Keyboard navigation for all interactive elements
+- Screen reader support
+- Proper semantic HTML
+- ARIA labels where necessary
+- Color contrast ratios (4.5:1 for normal text, 3:1 for large text)
+
+**Testing:**
+- Manual keyboard navigation testing
+- Screen reader testing (NVDA/JAWS)
+- Lighthouse accessibility audit
+- axe DevTools scanning
+
+### 12.3 Browser Support
+
+**Target Browsers:**
+- Chrome (last 2 versions)
+- Firefox (last 2 versions)
+- Safari (last 2 versions)
+- Edge (last 2 versions)
+
+**Mobile:**
+- iOS Safari (last 2 versions)
+- Chrome Android (last 2 versions)
+
+### 12.4 Security
+
+**Client-Side Security:**
+- XSS prevention (React defaults + sanitization where needed)
+- CSRF protection (if not handled by backend)
+- Secure token storage
+- No sensitive data in localStorage or client-side code
+- Content Security Policy headers
+- HTTPS only in production
+
+**Dependency Security:**
+- Regular dependency updates
+- Security audit via `npm audit`
+- Automated security scanning (Dependabot, Snyk)
+
+### 12.5 SEO
+
+**Requirements:**
+- Semantic HTML structure
+- Proper meta tags (title, description)
+- Open Graph tags for social sharing
+- Sitemap generation
+- robots.txt configuration
+- Structured data where applicable
+
+---
+
+## 13. Implementation Priorities
+
+While detailed implementation planning is out of scope for this document, the following priority order is recommended:
+
+**Phase 1: Foundation**
+1. Project setup and configuration
+2. API client generation setup
+3. Authentication implementation
+4. Basic layout components
+
+**Phase 2: Core Features**
+1. User management pages
+2. Organization management pages
+3. Admin dashboard
+
+**Phase 3: Polish**
+1. Development showcase pages
+2. Advanced components
+3. Charts and analytics
+4. Documentation completion
+
+**Phase 4: Production Readiness**
+1. Performance optimization
+2. Accessibility audit and fixes
+3. Security hardening
+4. Testing implementation
+
+---
+
+## 14. Success Criteria
+
+The frontend template will be considered complete when:
+
+1. **Functionality:**
+ - All specified pages are implemented and functional
+ - Authentication flow works end-to-end
+ - User and organization CRUD operations work
+ - API integration is complete and reliable
+
+2. **Code Quality:**
+ - TypeScript strict mode passes without errors
+ - ESLint passes without warnings
+ - All code follows documented standards
+ - No console errors in production build
+
+3. **Documentation:**
+ - All required documentation files are complete
+ - Code examples are accurate and tested
+ - Architecture is clearly explained
+ - New developers can onboard using documentation alone
+
+4. **User Experience:**
+ - UI is responsive on all target devices
+ - Loading states are shown appropriately
+ - Error messages are user-friendly
+ - Dark mode works throughout the app
+
+5. **Developer Experience:**
+ - Clear project structure is easy to navigate
+ - API client generation works reliably
+ - Adding new features follows clear patterns
+ - Development environment is easy to set up
+
+---
+
+## 15. Backend API Endpoint Reference
+
+Complete reference of all backend API endpoints for frontend integration. All endpoints are prefixed with `/api/v1/`.
+
+### 15.1 Authentication Endpoints
+
+| Method | Endpoint | Purpose | Auth Required | Request Body | Response |
+|--------|----------|---------|---------------|--------------|----------|
+| POST | `/api/v1/auth/register` | Register new user account | No | `{email, password, first_name}` | User + tokens |
+| POST | `/api/v1/auth/login` | Authenticate user | No | `{email, password}` | User + access_token + refresh_token |
+| POST | `/api/v1/auth/login/oauth` | OAuth2-compatible login (Swagger UI) | No | Form data | tokens |
+| POST | `/api/v1/auth/refresh` | Refresh access token | Yes (refresh token) | `{refresh_token}` | New access_token + refresh_token |
+| GET | `/api/v1/auth/me` | Get current user from token | Yes | - | User object |
+| POST | `/api/v1/auth/logout` | Logout current device | Yes | - | Success message |
+| POST | `/api/v1/auth/logout-all` | Logout all devices | Yes | - | Success message |
+| POST | `/api/v1/auth/password-reset/request` | Request password reset email | No | `{email}` | Success message (always) |
+| POST | `/api/v1/auth/password-reset/confirm` | Reset password with token | No | `{token, new_password}` | Success message |
+
+**Authentication Response Format:**
+```typescript
+{
+ access_token: string; // JWT, expires in 15 minutes
+ refresh_token: string; // JWT, expires in 7 days
+ token_type: "bearer";
+ user: User;
+}
+```
+
+### 15.2 User Endpoints
+
+| Method | Endpoint | Purpose | Auth Required | Query Params | Response |
+|--------|----------|---------|---------------|--------------|----------|
+| GET | `/api/v1/users` | List all users (paginated) | Admin only | `page, page_size, search` | Paginated users |
+| GET | `/api/v1/users/me` | Get own profile | Yes | - | User object |
+| PATCH | `/api/v1/users/me` | Update own profile | Yes | `{first_name, last_name, phone, preferences}` | Updated user |
+| PATCH | `/api/v1/users/me/password` | Change own password | Yes | `{current_password, new_password}` | Success message |
+| GET | `/api/v1/users/{user_id}` | Get user by ID | Yes (own or admin) | - | User object |
+| PATCH | `/api/v1/users/{user_id}` | Update user | Yes (own or admin) | User fields | Updated user |
+| DELETE | `/api/v1/users/{user_id}` | Soft delete user | Admin only | - | Success message |
+
+**User Model Fields:**
+```typescript
+{
+ id: UUID;
+ email: string;
+ first_name: string; // Required
+ last_name: string | null;
+ phone_number: string | null;
+ is_active: boolean;
+ is_superuser: boolean;
+ preferences: Record | null;
+ created_at: datetime;
+ updated_at: datetime | null;
+}
+```
+
+### 15.3 Session Management Endpoints
+
+| Method | Endpoint | Purpose | Auth Required | Response |
+|--------|----------|---------|---------------|----------|
+| GET | `/api/v1/sessions/me` | List my active sessions | Yes | Array of sessions |
+| DELETE | `/api/v1/sessions/{session_id}` | Revoke specific session | Yes (own session) | Success message |
+| DELETE | `/api/v1/sessions/me/expired` | Cleanup expired sessions | Yes | Success message |
+
+**Session Model:**
+```typescript
+{
+ id: UUID;
+ device_name: string | null;
+ device_id: string | null;
+ ip_address: string | null;
+ location_city: string | null;
+ location_country: string | null;
+ last_used_at: datetime;
+ created_at: datetime;
+ expires_at: datetime;
+ is_current: boolean;
+}
+```
+
+### 15.4 Admin User Management Endpoints
+
+| Method | Endpoint | Purpose | Auth Required | Request Body | Response |
+|--------|----------|---------|---------------|--------------|----------|
+| GET | `/api/v1/admin/users` | List all users with filters | Admin only | `search, is_active, is_superuser, page` | Paginated users |
+| POST | `/api/v1/admin/users` | Create user (can set superuser) | Admin only | User fields + `is_superuser` | Created user |
+| GET | `/api/v1/admin/users/{user_id}` | Get user details | Admin only | - | User with relations |
+| PUT | `/api/v1/admin/users/{user_id}` | Update user (full update) | Admin only | All user fields | Updated user |
+| DELETE | `/api/v1/admin/users/{user_id}` | Soft delete user | Admin only | - | Success message |
+| POST | `/api/v1/admin/users/{user_id}/activate` | Activate user account | Admin only | - | Updated user |
+| POST | `/api/v1/admin/users/{user_id}/deactivate` | Deactivate user account | Admin only | - | Updated user |
+| POST | `/api/v1/admin/users/bulk-action` | Bulk activate/deactivate/delete | Admin only | `{action, user_ids[]}` | Results array |
+
+**Bulk Action Request:**
+```typescript
+{
+ action: "activate" | "deactivate" | "delete";
+ user_ids: UUID[];
+}
+```
+
+### 15.5 Organization Endpoints
+
+| Method | Endpoint | Purpose | Auth Required | Response |
+|--------|----------|---------|---------------|----------|
+| GET | `/api/v1/organizations` | List organizations | Yes | Array of organizations |
+| POST | `/api/v1/organizations` | Create organization | Yes | Created organization |
+| GET | `/api/v1/organizations/{org_id}` | Get organization details | Yes (member or admin) | Organization |
+| PUT | `/api/v1/organizations/{org_id}` | Update organization | Yes (admin of org) | Updated organization |
+| DELETE | `/api/v1/organizations/{org_id}` | Delete organization | Yes (admin of org) | Success message |
+
+**Organization Model:**
+```typescript
+{
+ id: UUID;
+ name: string;
+ slug: string; // URL-friendly identifier
+ description: string | null;
+ is_active: boolean;
+ settings: Record; // JSON settings
+ member_count: number; // Computed field
+ created_at: datetime;
+ updated_at: datetime | null;
+}
+```
+
+### 15.6 Admin Organization Management Endpoints
+
+| Method | Endpoint | Purpose | Auth Required | Request Body | Response |
+|--------|----------|---------|---------------|--------------|----------|
+| GET | `/api/v1/admin/organizations` | List all orgs with search | Admin only | `search, page` | Paginated orgs |
+| POST | `/api/v1/admin/organizations` | Create organization | Admin only | `{name, slug, description, settings}` | Created org |
+| GET | `/api/v1/admin/organizations/{org_id}` | Get org details | Admin only | - | Organization |
+| PUT | `/api/v1/admin/organizations/{org_id}` | Update organization | Admin only | Org fields | Updated org |
+| DELETE | `/api/v1/admin/organizations/{org_id}` | Delete organization | Admin only | - | Success message |
+| GET | `/api/v1/admin/organizations/{org_id}/members` | List organization members | Admin only | - | Array of members |
+| POST | `/api/v1/admin/organizations/{org_id}/members` | Add member with role | Admin only | `{user_id, role}` | Member object |
+| DELETE | `/api/v1/admin/organizations/{org_id}/members/{user_id}` | Remove member | Admin only | - | Success message |
+
+**Organization Member:**
+```typescript
+{
+ user_id: UUID;
+ user_email: string;
+ user_name: string; // first_name + last_name
+ role: "owner" | "admin" | "member";
+ joined_at: datetime;
+}
+```
+
+### 15.7 Response Formats
+
+**Success Response (Data):**
+```typescript
+{
+ data: T | T[]; // Single object or array
+ pagination?: { // For paginated endpoints
+ total: number;
+ page: number;
+ page_size: number;
+ total_pages: number;
+ has_next: boolean;
+ has_prev: boolean;
+ };
+}
+```
+
+**Success Response (Message):**
+```typescript
+{
+ success: true;
+ message: string;
+}
+```
+
+**Error Response:**
+```typescript
+{
+ success: false;
+ errors: Array<{
+ code: string; // e.g., "AUTH_001", "USER_002"
+ message: string;
+ field?: string; // Optional field name for form errors
+ }>;
+}
+```
+
+### 15.8 Common Query Parameters
+
+| Parameter | Type | Description | Default | Example |
+|-----------|------|-------------|---------|---------|
+| `page` | integer | Page number (1-indexed) | 1 | `?page=2` |
+| `page_size` | integer | Items per page | 20 | `?page_size=50` |
+| `search` | string | Search term (name, email, etc.) | - | `?search=john` |
+| `is_active` | boolean | Filter by active status | - | `?is_active=true` |
+| `is_superuser` | boolean | Filter by superuser status | - | `?is_superuser=false` |
+| `sort_by` | string | Sort field | - | `?sort_by=created_at` |
+| `sort_order` | string | Sort direction (asc/desc) | desc | `?sort_order=asc` |
+
+### 15.9 Authentication Header Format
+
+All authenticated requests must include:
+
+```
+Authorization: Bearer {access_token}
+```
+
+Example:
+```typescript
+headers: {
+ 'Authorization': `Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...`,
+ 'Content-Type': 'application/json'
+}
+```
+
+### 15.10 Rate Limiting
+
+Backend implements rate limiting per endpoint:
+- **Auth endpoints**: 5 requests/minute
+- **Read operations**: 60 requests/minute
+- **Write operations**: 10-20 requests/minute
+
+Rate limit headers in response:
+```
+X-RateLimit-Limit: 60
+X-RateLimit-Remaining: 45
+X-RateLimit-Reset: 1234567890
+```
+
+When rate limit exceeded, backend returns `429 Too Many Requests`.
+
+---
+
+## Appendix A: Technology Versions
+
+Latest stable versions as of document creation:
+
+- Next.js: 15.x
+- React: 18.x
+- TypeScript: 5.x
+- Tailwind CSS: 3.x
+- TanStack Query: 5.x
+- Zustand: 4.x
+- Recharts: 2.x
+- Axios: 1.x
+- react-hook-form: 7.x
+- zod: 3.x
+
+---
+
+## Appendix B: Useful Resources
+
+- **Next.js Documentation:** https://nextjs.org/docs
+- **TanStack Query Documentation:** https://tanstack.com/query/latest
+- **shadcn/ui Documentation:** https://ui.shadcn.com
+- **Tailwind CSS Documentation:** https://tailwindcss.com/docs
+- **Zustand Documentation:** https://docs.pmnd.rs/zustand
+- **OpenAPI TypeScript Codegen:** https://github.com/ferdikoomen/openapi-typescript-codegen
+- **Hey API:** https://github.com/hey-api/openapi-ts
+
+---
+
+## Document Metadata
+
+- **Version:** 1.0
+- **Date:** October 31, 2025
+- **Status:** Draft
+- **Next Review:** Upon implementation start