veza/apps/web/docs/ARCHITECTURE.md
senke 8b1644640d refactor(audit-2.1,2.6): unify views and pages to features/*/pages pattern
- Migrate LiveView, GearView, PurchasesView, SocialView, AnalyticsView into features
- Create features: admin, developer, seller; add QueuePage, WishlistPage
- Migrate pages/marketplace to features/marketplace
- Remove components/views/ and pages/ legacy directories
- Update lazyExports, docs (ARCHITECTURE)
- Mark audit 2.1, 2.6 as done

Refs: AUDIT_TECHNIQUE_INTEGRAL_2026_02_15.md items 2.1, 2.6
2026-02-15 14:30:40 +01:00

131 lines
4.5 KiB
Markdown

# Veza Frontend Architecture Guide
**Status:** Living Document
**Version:** 2.0 (Post-Audit 2026)
This document outlines the architectural principles, patterns, and rules that govern the Veza frontend. It supersedes previous ad-hoc audit reports.
---
## 1. Core Philosophy: "Visual First"
> "If it can't be rendered in Storybook, it is architecturally broken."
We follow a **Storybook-Driven Development** (SDD) approach.
- **Isolation:** Every component must be renderable in isolation. Dependencies (Providers, Router, Store) must be explicit.
- **Verification:** Storybook is our primary verification tool for UI logic and layout.
---
## 2. State Management Strategy
We distinguish three types of state. Mixing them is strictly forbidden.
### 2.1. Server State (Data) -> `React Query`
Data that belongs to the backend (Users, Tracks, Playlists).
- **Tool:** `@tanstack/react-query`
- **Rule:** Never copy server data into a global store (Zustand) unless strictly necessary for client-side manipulation (e.g., a complex audio editor buffer).
- **Caching:** Managed automatically by query keys.
### 2.2. Client Global State (App) -> `Zustand`
Data that is truly global to the client session (Auth Token, Shopping Cart, Audio Player Status).
- **Tool:** `zustand`
- **Rule:** Use atomic selectors to prevent render-thrashing.
- **Structure:**
- `authStore`: User session.
- `cartStore`: E-commerce state (Items, Total).
- `playerStore`: Audio playback state.
**Legacy Note:** `React Context` is BANNED for high-frequency state updates. It is reserved for dependency injection (Theme, i18n).
### 2.3. UI Local State -> `useState` / `useReducer`
Ephemeral state specific to a component (Modal Open/Close, Form Inputs).
- **Rule:** If it doesn't need to persist when navigating away, it stays local.
---
## 3. Component Engineering
We adhere to the **Smart vs Dumb** (Container vs Presentational) separation to ensure testability.
### 3.1. Dumb Components (UI)
- **Role:** Render props into HTML. Emit events via callbacks.
- **Dependencies:** ZERO. No explicit side-effects, no API calls, no Context consumers (except Theme).
- **Testing:** Storybook.
```tsx
// ✅ Correct Dumb Component
export const ProductCard = ({ title, price, onAddToCart }: Props) => (
<div onClick={onAddToCart}>{title} - {price}</div>
);
```
### 3.2. Smart Components (Containers)
- **Role:** Wire data to UI.
- **Dependencies:** Allowed (`useQuery`, `useCartStore`, `useParams`).
- **Testing:** Integration Tests (MSW + Storybook play functions).
```tsx
// ✅ Correct Smart Component
export const ProductCardContainer = ({ id }) => {
const { data } = useProduct(id);
const addToCart = useCartStore(s => s.addItem);
return <ProductCard title={data.title} onAddToCart={() => addToCart(data)} />;
};
```
---
## 4. Design System & Styling
We use **Tailwind CSS** with a rigorous Design System (Kodo).
- **Tokens Only:** Do not use arbitrary values (e.g., `w-[350px]`). Use design tokens (`w-sidebar`).
- **Dark Mode:** All UI/Layout components must implement `dark:` variants.
- **Icons:** `lucide-react`. Icons must inherit color via `currentColor`.
---
## 5. Storybook Usage
Storybook is not optional. It is the definition of "Done".
### 5.1. Decorators
Use granular decorators from `src/stories/decorators.tsx` instead of global wrapping in `preview.tsx`.
- `withToast`: Injects ToastProvider.
- `withRouter`: Injects MemoryRouter.
- `withStoreState`: Mocks Zustand state.
### 5.2. Interaction Testing
Critical user flows (e.g., Add to Cart) must have a `.play` function in their story to verify interaction without manual testing.
---
## 6. Testing Pyramid
1. **Unit (Vitest):** Utilities, Store Reducers, Hooks.
2. **Integration (Storybook + Vitest):** Component wiring, Props interface.
3. **E2E (Playwright):** Critical Paths (Login, Checkout, Signup).
---
## 7. Feature Structure (Audit 2.1)
**Pattern unique : `features/*/pages/`**
- Toutes les pages principales vivent dans `src/features/<domain>/pages/`.
- Chaque feature peut avoir : `pages/`, `components/`, `hooks/`, `services/`, `types/`.
- Les routes chargent via `lazyExports.ts` : `import('@/features/<domain>/pages/<Page>')`.
- Référence : [FULL_LAYOUT_PAGE.md](FULL_LAYOUT_PAGE.md).
---
## 8. Anti-Patterns (Dos & Don'ts)
| ❌ Don't | ✅ Do |
| :--- | :--- |
| `useContext(CartContext)` | `useCartStore(selector)` |
| `w-[17px]` | `w-4` or `w-5` (stick to grid) |
| Props Drilling (> 3 levels) | Composition (Slots) or Context (if static) |
| API calls in `useEffect` | `useQuery` |
| `any` type | Generated types from OpenAPI |