Frontend Feature (Next.js 15 + React 19)
The frontend lives in frontend/src/ — App Router, TypeScript, Tailwind, next-intl, and Zustand. Routes are locale-prefixed: app/[locale]/….
Layout
| Path | Purpose |
|---|---|
src/app/[locale]/… |
Pages (route groups: (dashboard), (marketing), (auth)) |
src/app/api/… |
Next.js route handlers that proxy to the backend |
src/lib/ |
API clients (api-client.ts, *-api.ts), query-keys.ts, helpers |
src/components/ |
UI by domain (chat/, kb/, dashboard/, ui/, …) |
src/stores/ |
Zustand stores (one per concern, re-exported from index.ts) |
src/hooks/ |
useChat, useWebSocket, etc. |
Steps
Page — add
src/app/[locale]/(dashboard)/<feature>/page.tsx. Default to a Server Component; add"use client"only where you need interactivity. Read params via the async App Router APIs.Data access — add a typed client in
src/lib/<feature>-api.tsbuilt onapi-client.ts. Don't scatterfetchcalls in components. For server-side fetching useserver-api.ts. If the backend needs a same-origin proxy (auth cookies), add a handler undersrc/app/api/….Caching keys — register query keys in
src/lib/query-keys.tsso cache invalidation stays consistent.Client state — if the feature needs shared client state, add a store in
src/stores/<feature>-store.tsand export it fromstores/index.ts. Keep server data in the data layer; use stores for UI/ephemeral state.Components — put reusable pieces in
src/components/<domain>/; compose primitives fromsrc/components/ui/. Keep components under ~100 lines — extract when they grow.i18n — user-facing copy goes through
next-intlmessages, not hardcoded strings. Add keys to the message catalog and read them withuseTranslations/getTranslations.Verify:
cd frontend bun run type-check && bun run lint bun dev # check the page renders against a running backend (make dev)
Rules
- Server Components by default;
"use client"only when needed (state, effects, event handlers). - All API calls go through
src/lib/clients; components consume hooks/clients, not rawfetch. - Localized strings via
next-intl— never hardcode user-facing copy. - Match the existing folder-by-domain structure; reuse
components/ui/primitives.