My App
Architecture/FSD

L'architecture en couches

Le FSD organise le code en couches avec des règles de dépendance très strictes. De la plus haute (spécifique à l'application) à la plus basse (générique) :

src/
├── app/        /* Initialisation de l'application */
├── processes/  /* (Optionnel) Scénarios complexes inter-pages */
├── pages/      /* Les vues et le routage */
├── widgets/    /* Gros blocs UI autonomes */
├── features/   /* Interactions utilisateur spécifiques */
├── entities/   /* Entités métier */
└── shared/     /* Code infrastructurel réutilisable */

Regardons en détail chaque couche avec des exemples concrets.

La couche app

C'est le point d'entrée. Elle contient la configuration globale (providers, routeur, styles globaux).

/* app/App.tsx */
import { StoreProvider } from './providers/StoreProvider';
import { RouterProvider } from './providers/RouterProvider';
import './styles/globals.css';

/* Seule cette couche a le droit d'importer absolument tout */
export const App = () => {
  return (
    <StoreProvider>
        <RouterProvider />
    </StoreProvider>
  );
};

La couche pages

Elle contient la définition des routes. Chaque page assemble des éléments des couches inférieures.

/* pages/product-details/ui/ProductDetailsPage.tsx */
import { ProductCard } from '@/entities/product';
import { AddToCartButton } from '@/features/add-to-cart';
import { ProductReviews } from '@/widgets/product-reviews';

/* On compose la page avec des widgets, features et entities */
export const ProductDetailsPage = () => {
  return (
    <div className="product-page">
      <ProductCard product={product} />
      <AddToCartButton productId={product.id} />
      <ProductReviews productId={product.id} />
    </div>
  );
};

La couche widgets

Ce sont de gros blocs UI indépendants qui mélangent plusieurs entités et features (ex: un header, une barre latérale).

/* widgets/header/ui/Header.tsx */
import { Logo } from '@/shared/ui/Logo';
import { SearchBar } from '@/features/search';
import { CartButton } from '@/features/cart';

/* Le widget a conscience du métier, mais pas de la page où il se trouve */
export const Header = () => {
  return (
    <header>
      <Logo />
      <SearchBar />
      <CartButton />
    </header>
  );
};

La couche features

Elle représente les actions de l'utilisateur (ajouter au panier, liker un post, se connecter).

/* features/add-to-cart/ui/AddToCartButton.tsx */
import { Button } from '@/shared/ui/Button';
import { useAddToCart } from '../model/useAddToCart';

/* Une action encapsulée avec sa propre logique métier */
export const AddToCartButton = ({ productId }) => {
  const { addToCart, isLoading } = useAddToCart();

  return (
    <Button onClick={() => addToCart(productId)} disabled={isLoading}>
      {isLoading ? 'Ajout...' : 'Ajouter au panier'}
    </Button>
  );
};

La couche entities

Ce sont nos modèles de données métier (produit, utilisateur, commande). Elle contient l'affichage de base de la donnée, sans interactions complexes.

/* entities/product/ui/ProductCard.tsx */
import { Card } from '@/shared/ui/Card';
import { Price } from '@/shared/ui/Price';

/* Représente ce qu'EST la donnée, pas ce que l'utilisateur peut FAIRE avec */
export const ProductCard = ({ product }) => {
  return (
    <Card>
      <img src={product.imageUrl} alt={product.title} />
      <h3>{product.title}</h3>
      <Price amount={product.price} />
    </Card>
  );
};

La couche shared

C'est la fondation technique. Elle ne contient aucune logique métier (boutons UI génériques, utilitaires, configuration Axios).

/* shared/ui/Button/Button.tsx */
/* Un composant agnostique réutilisable partout */
export const Button = ({ variant = 'primary', children, ...props }) => {
  return (
    <button className={`btn-${variant}`} {...props}>
      {children}
    </button>
  );
};