- 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
131 lines
4.5 KiB
Markdown
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 |
|