--- description: Frontend folder structure — ui vs non-ui, thin pages, feature layout globs: frontend/src/** alwaysApply: false --- # Frontend component structure ## Rules | Kind | Location | |------|----------| | Cross-feature UI | `components/ui/shared/` | | Feature UI | `components/ui/{feature}/` | | Cross-feature non-UI | `components/shared/` | | Feature non-UI | `components/{feature}/` | | Route logic | `components/ui/{feature}/{Feature}Page.tsx` | | App routes | `app/**/page.tsx` — **thin wrapper only** | ## Thin page pattern ```tsx 'use client'; import { PatientsPage } from '@/components/ui/patient/PatientsPage'; export default function Page() { return ; } ``` Reference: `app/.../treatment/page.tsx` + `components/ui/treatment/TreatmentWorkspace.tsx`. ## Do not - Put React components (`.tsx` with JSX) in `components/` outside `ui/`. - Put pure helpers (`.ts`, no JSX) inside `components/ui/`. - Put business logic, API calls, or large forms directly in `app/**/page.tsx`. ## API & errors - API clients: `lib/api/`. - Catch blocks: `getUserFacingError(err, tErrors, fallback)` from `components/shared/formatApiError.ts`. ## Toasts - Use `useToast()` for transient page feedback — rendered globally by `ToastProvider` in dashboard layout (fixed bottom, above dialogs). - Do **not** add `` inside pages or dialogs. - Form/dialog validation: inline error text near the field or submit button, not a toast. ## When adding UI 1. Check `components/ui/shared/` for an existing primitive. 2. Check the feature's `ui/{feature}/` folder for an existing pattern. 3. Add i18n keys to en, fa, and nl.