# Architecture Frontend — Next.js 14 --- ## Structure ``` apps/frontend/ ├── app/ # Next.js App Router │ ├── [locale]/ # i18n wrapper (fr, en) — next-intl │ │ ├── about/ │ │ ├── blog/ │ │ ├── booking/ # Flux de réservation │ │ ├── careers/ │ │ ├── carrier/ # Portail carrier (magic link) │ │ ├── compliance/ │ │ ├── contact/ │ │ ├── dashboard/ # Application protégée │ │ │ ├── bookings/ │ │ │ ├── csv-bookings/ │ │ │ ├── search/ │ │ │ ├── settings/ │ │ │ ├── admin/ │ │ │ └── wiki/ │ │ ├── docs/ │ │ ├── forgot-password/ │ │ ├── login/ │ │ ├── pricing/ │ │ ├── register/ │ │ ├── reset-password/ │ │ └── verify-email/ │ └── api/v1/ # API routes Next.js (proxy) │ ├── src/ │ ├── components/ # Composants React │ │ ├── admin/ │ │ ├── blog/ │ │ ├── bookings/ │ │ ├── docs/ │ │ ├── layout/ │ │ ├── organization/ │ │ ├── rate-search/ │ │ └── ui/ # Composants shadcn/ui (Radix UI) │ ├── hooks/ # Custom hooks (TanStack Query) │ ├── lib/ │ │ ├── api/ # Client fetch avec auto-refresh JWT │ │ │ ├── client.ts # get/post/patch/del/upload/download │ │ │ ├── auth.ts │ │ │ ├── bookings.ts │ │ │ ├── rates.ts │ │ │ └── ... │ │ ├── context/ # AuthContext, CookieContext │ │ └── providers/ # QueryProvider (TanStack Query) │ ├── types/ # Types TypeScript │ └── utils/ # Export Excel, PDF │ ├── i18n/ # Config next-intl ├── messages/ │ ├── fr.json # Traductions français │ └── en.json # Traductions anglais └── middleware.ts # Auth + i18n routing ``` --- ## i18n (Internationalisation) Le frontend supporte **français** (par défaut) et **anglais** via `next-intl`. Routes : `/fr/login`, `/en/login`, etc. ```typescript // i18n/routing.ts export const routing = defineRouting({ locales: ['fr', 'en'], defaultLocale: 'fr', }); ``` Le middleware `middleware.ts` combine la protection d'auth **et** le routing i18n. --- ## Client API `src/lib/api/client.ts` — wrapper fetch avec auto-refresh JWT : ```typescript // Toutes les requêtes passent par ces fonctions export const get = (url: string): Promise export const post = (url: string, body: unknown): Promise export const patch = (url: string, body: unknown): Promise export const del = (url: string): Promise export const upload = (url: string, formData: FormData): Promise export const download = (url: string): Promise ``` - Sur 401 : refresh automatique du token, retry de la requête - Tokens : localStorage ET cookie `accessToken` (pour le middleware Next.js) --- ## State management - **Données serveur** : TanStack Query v5 (`@tanstack/react-query`) - **État global UI** : zustand (minimal) - **Formulaires** : react-hook-form + zod ```typescript // Pattern hook standard export function useBookings(filters?: BookingFilters) { return useQuery({ queryKey: ['bookings', filters], queryFn: () => bookingsApi.list(filters), }); } ``` --- ## Protection des routes `middleware.ts` vérifie le cookie `accessToken` avant chaque route. **Routes publiques exactes** : `/fr`, `/en`, `/` **Routes publiques par préfixe** : `/login`, `/register`, `/forgot-password`, `/reset-password`, `/verify-email`, `/about`, `/blog`, `/pricing`, `/contact`, `/careers`, `/press`, `/security`, `/privacy`, `/terms`, `/cookies`, `/compliance`, `/carrier` Toutes les autres routes → redirection `/login?redirect=` --- ## Design system | Élément | Valeur | |---------|--------| | Couleur primaire | Navy `#10183A` | | Couleur accent | Turquoise `#34CCCD` | | Succès | Green `#067224` | | Fond neutre | Gray `#F2F2F2` | | Font headings | Manrope | | Font body | Montserrat | | UI components | shadcn/ui (Radix UI) | | Icônes | lucide-react | --- ## Conventions - Pas de fetch direct — toujours via `src/lib/api/*.ts` - Les hooks wrappent TanStack Query, pas de `useEffect` pour les données - `strict: false` en frontend (contrairement au backend) - Alias `@/*` → `./src/*` - La landing page est en **français**