3.2 KiB
3.2 KiB
Frontend API client and auth integration
This page documents the frontend integration points you’ll touch when changing how the UI talks to the backend or how auth is applied.
Related docs
API base URL
The frontend uses NEXT_PUBLIC_API_URL as the single source of truth for where to send API requests.
- Code:
frontend/src/lib/api-base.ts - Behavior:
- reads
process.env.NEXT_PUBLIC_API_URL - normalizes by trimming trailing slashes
- throws early if missing/invalid
- reads
In Docker Compose, compose.yml sets NEXT_PUBLIC_API_URL both:
- as a build arg (for
next build), and - as a runtime env var.
API client layout
Generated client
- Location:
frontend/src/api/generated/* - Generator: Orval
- Config:
frontend/orval.config.ts - Script:
cd frontend && npm run api:gen - Convenience target:
make api-gen
- Config:
By default, Orval reads the backend OpenAPI schema from:
ORVAL_INPUT(if set), otherwisehttp://127.0.0.1:8000/openapi.json
Output details (from orval.config.ts):
- Mode:
tags-split - Target index:
frontend/src/api/generated/index.ts - Schemas:
frontend/src/api/generated/model - Client:
react-query - All requests go through the custom mutator below.
Custom fetch / mutator
All generated requests go through:
- Code:
frontend/src/api/mutator.ts - What it does:
- resolves
NEXT_PUBLIC_API_URLand builds the full request URL - sets
Content-Type: application/jsonwhen there’s a body - injects
Authorization: Bearer <token>when a Clerk session token is available - converts non-2xx responses into a typed
ApiError(status + parsed response)
- resolves
Auth enablement and token injection
Clerk enablement (publishable key gating)
Clerk is enabled in the frontend only when NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY looks valid.
- Gating helper (dependency-free):
frontend/src/auth/clerkKey.ts - UI-safe wrappers/hooks:
frontend/src/auth/clerk.tsx- provides
SignedIn,SignedOut,SignInButton,SignOutButton,useUser, anduseAuth - returns safe fallbacks when Clerk is disabled (to allow secretless builds/prerender)
- provides
Token injection
When the UI makes an API request, the mutator attempts to read a token from the Clerk session:
- Code:
frontend/src/api/mutator.ts(resolveClerkToken()) - If a token is available, the request includes:
Authorization: Bearer <token>
Route protection (middleware)
Request-time route protection is implemented via Next.js middleware:
- Code:
frontend/src/proxy.ts - Behavior:
- when Clerk is enabled: uses
clerkMiddleware()to enforce auth on non-public routes - when Clerk is disabled: passes all requests through
- when Clerk is enabled: uses
Common workflows
Update the backend API and regenerate the client
- Run the backend so OpenAPI is available:
# from repo root
cp backend/.env.example backend/.env
make backend-migrate
cd backend && uv run uvicorn app.main:app --reload --port 8000
- Regenerate the client:
# from repo root
make api-gen
# or from frontend/
ORVAL_INPUT=http://127.0.0.1:8000/openapi.json npm run api:gen
- Review diffs under
frontend/src/api/generated/*.