API Layer Pattern
Typed API communication layer between frontend and backend.
Frontend API Organization
All API modules live in frontend/src/lib/api/ (38 files including core and types).
Core Instance
frontend/src/lib/api/core.ts provides the shared Axios instance with:
- JWT token injection from auth store
- Automatic token refresh on 401 responses
- Request/response interceptors for error normalization
- Base URL configuration per environment
Domain Modules
Each entity has a dedicated API module with typed request/response:
| Module | Entity |
|---|---|
buildings.ts | Buildings |
projects.ts | Projects |
contacts.ts | Contacts |
quotes.ts | Quotes |
invoices.ts | Invoices |
files.ts / files-api.ts | Files |
funding.ts | Funding Programs / Funding Applications |
portal.ts | Portal |
workflow.ts | Workflows |
document-obtaining.ts | Document Obtaining |
Module Structure
// frontend/src/lib/api/buildings.ts
export const buildingsApi = {
list: (projectId: string) =>
api.get<Building[]>(`/api/projects/${projectId}/buildings`),
get: (id: string) =>
api.get<Building>(`/api/buildings/${id}`),
create: (data: CreateBuildingInput) =>
api.post<Building>('/api/buildings', data),
};Backend Route Validation
Routes use OpenAPIHono for auto-generated OpenAPI specs. All inputs are validated with Zod schemas before reaching services:
app.openapi(route, async (c) => {
const validated = c.req.valid('json'); // Zod-validated
const { buildings } = c.var.services;
return c.json(await buildings.create(validated));
});Shared Types
Request/response types shared between frontend and backend live in Shared Layer:
shared/api-types.ts—ApiResponse<T>,ApiError,isApiError()shared/types.ts— Entity types,LocalizedTextshared/validation-constants.ts— Field length limits, regex patterns
See Also
- React Query Pattern — queries that consume these API modules
- Validation Pattern — Zod schemas on both sides
- Frontend Architecture — frontend structure
- Backend Architecture — backend route organization
- Error Handling Pattern — API error contract
- Shared Layer — cross-boundary types