Frontend Overview
The frontend is a React single-page application built with TypeScript, Tailwind CSS, and shadcn/ui components.
Stack
| Technology | Version | Purpose |
|---|---|---|
| React | 18 | UI framework |
| TypeScript | 5 | Type safety |
| Tailwind CSS | 3 | Utility-first styling |
| shadcn/ui | latest | Component primitives |
| TanStack React Query | 5 | Server state management |
| React Router | 6 | Client-side routing |
| Vite | 5 | Build tool and dev server |
| sonner | latest | Toast notifications |
Architecture
State Management
- Server state: Managed by TanStack React Query (caching, refetching, mutations)
- URL state: Filter parameters persisted in URL search params
- Local state: React
useStatefor form inputs and UI state - No global state management library (Redux, Zustand) — not needed
Query Keys
All React Query keys are centralized in lib/query-keys.ts for consistency:
export const queryKeys = {
clients: {
all: ['clients'] as const,
detail: (key: string) => ['clients', key] as const,
worklogs: (key: string, from: string, to: string) =>
['clients', key, 'worklogs', from, to] as const,
},
invoices: {
all: ['invoices'] as const,
list: (filters: InvoiceFilters) => ['invoices', filters] as const,
detail: (id: string) => ['invoices', id] as const,
editHistory: (id: string) => ['invoices', id, 'edit-history'] as const,
},
};
Development
# Start dev server (port 5173)
make run-frontend
# Or directly
cd frontend && npm run dev
# Lint
cd frontend && npx eslint .
# Format
cd frontend && npx prettier --write "src/**/*.{ts,tsx,css}"
Configuration
The frontend proxies API requests to the backend via Vite's dev server proxy:
// vite.config.ts
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8081',
changeOrigin: true,
},
},
}
Conventions
- Components: PascalCase (
InvoiceRegistry.tsx) - Hooks:
use{Name}(useInvoices.ts) - API functions: verb + noun (
fetchInvoices,generateInvoice) - Event handlers:
handle{Event}(handleSubmit,handleDelete) - Search inputs: Debounced at 300ms
- Toasts:
sonnerwith contextual messages - Accessibility:
aria-labelon icon buttons,aria-invalidon form errors, keyboard navigation