Projet fullstack : Souk Atlas, une place de marché de A à Z
Quitter

Leçon 1 sur 12 · Conception

Le projet Souk Atlas : besoins, maquettes, architecture et dépôt Git

1 h 00 Node.js 22 (Debian, git, npm, python3)

Objectif

Poser les fondations du projet fil rouge de cette formation : Souk Atlas, une place de marché où des artisans marocains vendent tapis, poteries, cuirs et bijoux, et où les clients paient par virement bancaire. À la fin de la leçon, vous savez ce que l'application doit faire, à quoi elle ressemble, comment ses trois briques se parlent, et vous avez un dépôt Git propre, sans aucun secret dedans.

L'essentiel

  • Un projet fullstack commence sur papier : récits utilisateur, maquettes, liste de ce qui est hors périmètre.
  • Souk Atlas a trois briques : un front React (le navigateur), une API Node.js/Express (les règles métier) et une base PostgreSQL (la vérité des données).
  • Le navigateur ne parle jamais directement à la base : tout passe par l'API, qui valide et recalcule.
  • Un seul dépôt Git (un « monorepo ») avec api/, web/ et docs/ suffit largement pour une petite équipe.
  • Les secrets (.env) ne vont jamais dans Git : on versionne un modèle .env.example à la place.

1. Ce que cette formation assemble

Vous avez appris les briques une par une dans les autres formations MasterLinux :

Brique Où l'avez-vous apprise ? Ce qu'on en fait ici
HTML, CSS, JavaScript, fetch formation Web (leçons 2.x et 3.2) l'interface et les appels à l'API
Node.js, Express formation Node.js l'API REST de la place de marché
React formation React le front : catalogue, panier, espace vendeur
SQL, PostgreSQL formation SQL le schéma et les requêtes
Docker, Compose formation Docker (leçons 1.4, 2.4, 2.5, 3.3) l'emballage et le déploiement
GitHub Actions formation CI/CD (leçons 1.2, 2.1, 2.2) les tests et la construction automatiques

Cette formation ne réexplique pas ces bases : elle montre comment les faire travailler ensemble sur un vrai produit, avec les décisions qu'un développeur fullstack prend chaque jour. Quand une notion a déjà été vue, nous vous renvoyons à la leçon concernée.

2. Le client et son besoin

Le client : une coopérative fictive, « Souk Atlas SARL », basée à Fès. Elle veut aider une cinquantaine d'artisans de Fès, Safi, Marrakech et Essaouira à vendre en ligne, sans dépendre d'une plateforme étrangère qui prend une grosse commission.

Ce qu'on sait de ses utilisateurs :

  • les acheteurs sont surtout au Maroc, sur téléphone, et beaucoup n'ont pas de carte bancaire utilisable en ligne ;
  • les artisans ne sont pas des informaticiens : leur écran doit être simple ;
  • la coopérative encaisse les virements sur son compte, puis reverse aux artisans.

D'où la décision la plus structurante du projet : le paiement se fait par virement bancaire. L'acheteur passe commande, reçoit le RIB de la coopérative et une référence à recopier dans le motif du virement ; un administrateur rapproche ensuite les virements reçus et marque les commandes « payées ». Le paiement par carte viendra dans une version 2.

3. Les récits utilisateur

Un récit utilisateur (user story) décrit un besoin du point de vue de celui qui l'a, en une phrase : « En tant que rôle, je fais quelque chose pour obtenir un bénéfice ». Il ne dit pas comment le coder.

Rôle Récit Priorité
Acheteur En tant qu'acheteur, je parcours le catalogue par catégorie et je cherche un produit par son nom indispensable
Acheteur En tant qu'acheteur, je remplis un panier et je vois le total en dirhams, livraison comprise indispensable
Acheteur En tant qu'acheteur, je passe commande et je reçois la référence à indiquer sur mon virement indispensable
Acheteur En tant qu'acheteur, je suis l'état de ma commande (en attente, payée, expédiée) indispensable
Vendeur En tant que vendeur, j'ajoute, modifie et retire mes produits indispensable
Vendeur En tant que vendeur, je vois les commandes payées et je les marque expédiées indispensable
Admin En tant qu'administrateur, je marque une commande payée quand le virement arrive indispensable
Acheteur En tant qu'acheteur, je laisse un avis sur un produit plus tard

Écrire la colonne priorité est aussi important que le reste : elle définit le produit minimum viable, ce qu'on livre en premier.

Et la liste hors périmètre, écrite noir sur blanc, évite les discussions sans fin : paiement par carte, application mobile native, messagerie entre acheteur et vendeur, gestion des retours. Ce n'est pas « jamais », c'est « pas dans cette version ».

4. Les maquettes

Avant de coder, on dessine les écrans. Un crayon et du papier suffisent, ou un outil comme Figma ou Penpot. Voici les cinq écrans de la version 1, en maquette « fil de fer » :

┌─────────────────────────────────────┐   ┌─────────────────────────────────────┐
│ SOUK ATLAS   [Rechercher…   ] 🛒 2  │   │ ← Catalogue                         │
├─────────────────────────────────────┤   │ ┌──────────┐  Bol en céramique Safi │
│ Tapis · Poterie · Cuir · Bijoux     │   │ │  photo   │  150,00 DH             │
│ ┌──────┐ ┌──────┐ ┌──────┐          │   │ └──────────┘  Atelier Belkhayat     │
│ │photo │ │photo │ │photo │          │   │  Quantité [1]  [Ajouter au panier]  │
│ │Tapis │ │Bol   │ │Babou-│          │   │  Description…                       │
│ │4500DH│ │150 DH│ │120 DH│          │   └─────────────────────────────────────┘
│ └──────┘ └──────┘ └──────┘          │        2. Fiche produit
│        ‹ 1 2 3 ›                    │
└─────────────────────────────────────┘
          1. Catalogue
┌─────────────────────────────────────┐   ┌─────────────────────────────────────┐
│ Panier                              │   │ Commande SA-2026-000123-77          │
│ Bol de Safi        x2    300,00 DH  │   │ À virer : 450,00 DH                 │
│ Babouches          x1    120,00 DH  │   │ RIB : 011 780 0000123456789012 34   │
│ Livraison                 30,00 DH  │   │ Motif : SA-2026-000123-77           │
│ Total (dont TVA 70 DH)   450,00 DH  │   │ Statut : en attente du virement     │
│ [Nom] [Téléphone] [Adresse] [Ville] │   └─────────────────────────────────────┘
│ [Valider la commande]               │        4. Confirmation
└─────────────────────────────────────┘
          3. Panier et livraison           5. Espace vendeur : mes produits, mes commandes

Les maquettes révèlent des questions que le texte cache : faut-il un compte pour commander ? (oui, pour suivre sa commande) ; la livraison est-elle offerte ? (au-delà de 500 DH) ; les prix sont-ils TTC ? (oui, comme dans tout commerce au Maroc ; la TVA de 20 % est incluse et affichée pour information).

Notez ces décisions dans docs/ : dans trois mois, personne ne s'en souviendra.

5. L'architecture

 Navigateur (téléphone, PC)
 ┌────────────────────────┐   HTTPS + JSON    ┌──────────────────────────┐    SQL     ┌──────────────┐
 │  Front React (Vite)    │ ────────────────▶ │  API Node.js / Express   │ ─────────▶ │  PostgreSQL  │
 │  catalogue, panier,    │ ◀──────────────── │  validation, prix, stock │ ◀───────── │  tables,     │
 │  espace vendeur        │   cookie session  │  sessions, commandes     │            │  contraintes │
 └────────────────────────┘                   └──────────────────────────┘            └──────────────┘
        fichiers statiques servis par nginx         port 3000 (local)                  port 5432 (local)

Chaque brique a une responsabilité :

  • Le front affiche et collecte. Il peut calculer un total « pour information », mais il n'a aucune autorité : un utilisateur malin peut modifier n'importe quel calcul fait dans son navigateur.
  • L'API applique les règles : elle relit les prix dans la base, vérifie le stock, contrôle qui a le droit de faire quoi, et refuse le reste avec un code d'erreur clair.
  • La base garde les données et protège leur cohérence avec des contraintes (un stock ne peut pas être négatif, une commande appartient forcément à un acheteur existant).

Pourquoi ces technologies ? Pas par mode : React a un écosystème énorme et des développeurs disponibles au Maroc ; Express est le serveur Node.js le plus répandu et le plus documenté ; PostgreSQL offre des transactions solides, indispensables dès qu'on manipule de l'argent et du stock. Une autre équipe aurait pu choisir autre chose ; l'important est de savoir justifier son choix.

Le site de la documentation React propose une méthode pour découper une interface en composants à partir d'une maquette (« Penser en React ») : c'est exactement ce que nous ferons au niveau 3.

6. Le dépôt Git

Un seul dépôt pour tout le projet :

souk-atlas/
├── README.md            ← ce qu'est le projet, comment le lancer
├── .gitignore           ← node_modules/, .env, dist/…
├── .env.example         ← les variables attendues, SANS valeurs secrètes
├── compose.yaml         ← (niveau 4) la pile complète
├── docs/
│   ├── BESOINS.md       ← récits utilisateur, hors périmètre, décisions
│   ├── API.md           ← (leçon 1.3) le contrat de l'API
│   └── maquettes/
├── api/                 ← le back-end Node.js
│   ├── package.json
│   ├── migrations/      ← (leçon 1.2) le schéma SQL, versionné
│   ├── src/
│   └── test/
└── web/                 ← le front React
    ├── package.json
    └── src/

Créez-le :

mkdir -p souk-atlas/{api/src,web/src,docs}
cd souk-atlas
touch api/src/.gitkeep web/src/.gitkeep     # Git ne suit pas les dossiers vides
printf '%s\n' 'node_modules/' '.env' 'dist/' 'coverage/' '*.log' > .gitignore
git init -b main
git add .
git commit -m "Initialisation du projet Souk Atlas"

Les secrets : .env et .env.example

L'API aura besoin d'une adresse de base de données et d'un secret de session. Ces valeurs vivent dans un fichier .env, différent sur chaque machine, et jamais commité :

# .env.example  (versionné : il documente ce qu'il faut remplir)
NODE_ENV=development
PORT=3000
DATABASE_URL=postgres://souk:souk@localhost:5432/souk_atlas
SESSION_SECRET=

Chaque développeur copie le modèle : cp .env.example .env, puis remplit ses valeurs. Vérifiez qu'il est bien ignoré :

git status --short        # .env ne doit PAS apparaître
git check-ignore -v .env  # affiche la règle du .gitignore qui l'ignore

Un mot de passe poussé sur GitHub, même une minute, doit être considéré comme compromis : il faut le changer. L'historique Git garde tout.

La façon de travailler

Pour une petite équipe : la branche main est toujours livrable ; chaque fonctionnalité se développe sur une branche (feature/panier), puis arrive dans main par une pull request relue et testée automatiquement (leçon 4.2). Des messages de commit clairs (« Ajoute le calcul de la livraison ») valent mieux qu'une convention compliquée que personne ne suit.

7. Le plan de la formation

Niveau Leçons Ce que vous produisez
1 Conception 1.1 à 1.3 besoins, schéma SQL, contrat de l'API
2 Back-end 2.1 à 2.4 l'API : squelette, catalogue, comptes, commandes
3 Front-end 3.1 et 3.2 le front React complet
4 Mise en production 4.1 à 4.3 tests, conteneurs, CI, déploiement sur VPS

Les labs se font dans un conteneur Node.js sans accès à Internet : impossible d'y installer Express, React ou PostgreSQL. Vous y écrirez donc les briques métier du projet (validation, calcul du panier, référence de virement, routeur HTTP, schéma SQL…) avec les seuls modules intégrés à Node.js, et chaque vérification exécute votre code. Ces briques sont exactement celles que vous brancherez ensuite dans Express et React sur votre propre machine.

Pièges fréquents

  • Coder avant de savoir quoi coder : sans récits ni maquettes, on découvre les vraies questions (TTC ou HT ? compte obligatoire ?) au milieu du développement, et on refait.
  • Oublier le hors périmètre : chaque réunion ajoute « juste une petite fonction », et le projet ne sort jamais.
  • Commiter .env : ajoutez .env au .gitignore avant le premier git add ., pas après.
  • Faire confiance au front : un total, un prix ou un rôle envoyé par le navigateur peut être modifié par n'importe qui avec les outils de développement.

Lab

Vous créez le squelette du dépôt Souk Atlas dans /root/souk-atlas : l'arborescence api/, web/, docs/ et un README ; le document des besoins avec ses récits utilisateur et son hors périmètre ; la protection des secrets (.gitignore et .env.example) ; enfin le dépôt Git sur la branche main avec un premier commit, en vérifiant qu'un vrai fichier .env reste hors de Git.

Quiz

  1. Pourquoi le navigateur ne doit-il pas envoyer le prix d'un produit à l'API au moment de la commande ?
  2. Quelle est la différence entre .env et .env.example ?
  3. À quoi sert la liste « hors périmètre » dans le document des besoins ?
  4. Pourquoi Souk Atlas utilise-t-il une référence de commande dans le motif du virement ?
  5. Un collègue a poussé le vrai mot de passe de la base dans un commit, puis l'a retiré dans le commit suivant. Le problème est-il réglé ?
Réponses
  1. Parce que tout ce qui vient du navigateur peut être modifié par l'utilisateur. L'API ne reçoit que des identifiants de produits et des quantités, puis relit les prix dans la base.
  2. .env contient les vraies valeurs (mot de passe, secret) de cette machine et n'est jamais versionné ; .env.example est versionné, liste les variables attendues et ne contient aucune valeur secrète.
  3. À fixer ce qui ne sera pas fait dans cette version, pour protéger le délai et éviter les ajouts permanents.
  4. Pour que l'administrateur puisse rapprocher chaque virement reçu de la bonne commande ; la clé de contrôle (leçon 2.4) détecte en plus les fautes de frappe.
  5. Non : l'historique Git garde l'ancien commit. Il faut considérer le mot de passe comme compromis et le changer, puis éventuellement nettoyer l'historique.

Exercices pratiques

À réaliser sur Node.js 22 (Debian, git, npm, python3)

Le terminal en ligne ouvre bientôt. En attendant, réalisez ces tâches sur votre machine Linux, une machine virtuelle ou WSL.

  1. Créez le dossier du projet /root/souk-atlas avec les sous-dossiers api/src, web/src et docs, puis un README.md qui contient le nom « Souk Atlas » et décrit le projet en deux ou trois lignes.
    Afficher un indicemkdir -p crée toute l'arborescence d'un coup ; placez un fichier vide .gitkeep dans api/src et web/src pour que Git garde ces dossiers.
    Voir la solution
    mkdir -p /root/souk-atlas/api/src /root/souk-atlas/web/src /root/souk-atlas/docs && touch /root/souk-atlas/api/src/.gitkeep /root/souk-atlas/web/src/.gitkeep && mkdir -p /root/souk-atlas && printf '%s\n' '# Souk Atlas' '' 'Place de marché des artisans marocains : catalogue, panier en dirhams, commandes, espace vendeur, paiement par virement.' '' '## Dossiers' '' '- api/ : API Node.js (Express) et migrations PostgreSQL' '- web/ : application React' '- docs/ : besoins, maquettes, contrat de l'\''API' > /root/souk-atlas/README.md

    Vérification : cd /root/souk-atlas && test -d api/src && test -d web/src && test -d docs && grep -q "Souk Atlas" README.md

  2. Écrivez /root/souk-atlas/docs/BESOINS.md avec trois titres de niveau 2 : « ## Acheteur », « ## Vendeur » et « ## Hors périmètre », et au moins quatre récits utilisateur sous forme de puces qui commencent par « - En tant qu… » (« En tant qu'acheteur… », « En tant que vendeur… »).
    Afficher un indiceUn récit utilisateur suit le modèle : « En tant que <rôle>, je <action> (pour <bénéfice>) ». Écrivez le fichier avec cat > fichier <<'FIN' … FIN.
    Voir la solution
    mkdir -p /root/souk-atlas/docs && printf '%s\n' '# Souk Atlas — besoins' '' '## Acheteur' '' '- En tant qu'\''acheteur, je parcours le catalogue par catégorie et je cherche un produit par son nom.' '- En tant qu'\''acheteur, je remplis un panier et je vois le total en dirhams, livraison comprise.' '- En tant qu'\''acheteur, je passe commande et je reçois la référence à indiquer sur mon virement.' '' '## Vendeur' '' '- En tant que vendeur, j'\''ajoute, modifie et retire mes produits.' '- En tant que vendeur, je vois les commandes payées et je les marque expédiées.' '' '## Hors périmètre' '' '- Paiement par carte bancaire (prévu en version 2).' '- Application mobile native.' > /root/souk-atlas/docs/BESOINS.md

    Vérification : f=/root/souk-atlas/docs/BESOINS.md; grep -q "^## Acheteur" $f && grep -q "^## Vendeur" $f && grep -q "^## Hors p" $f && test "$(grep -c "^- En tant qu" $f)" -ge 4

  3. Préparez les secrets : un fichier /root/souk-atlas/.gitignore qui ignore node_modules/ et .env (une entrée par ligne), et un modèle /root/souk-atlas/.env.example qui déclare les variables DATABASE_URL= et SESSION_SECRET= (sans vraie valeur secrète).
    Afficher un indiceprintf '%s\n' 'node_modules/' '.env' > .gitignore écrit deux lignes d'un coup.
    Voir la solution
    mkdir -p /root/souk-atlas && printf '%s\n' 'node_modules/' '.env' 'dist/' 'coverage/' '*.log' > /root/souk-atlas/.gitignore && mkdir -p /root/souk-atlas && printf '%s\n' '# Copiez ce fichier en .env et remplissez les valeurs' 'NODE_ENV=development' 'PORT=3000' 'DATABASE_URL=postgres://souk:souk@localhost:5432/souk_atlas' 'SESSION_SECRET=' > /root/souk-atlas/.env.example

    Vérification : cd /root/souk-atlas && grep -Eq "^/?node_modules/?$" .gitignore && grep -Eq "^\.env$" .gitignore && grep -q "^DATABASE_URL=" .env.example && grep -q "^SESSION_SECRET=" .env.example

  4. Créez un fichier local /root/souk-atlas/.env (par exemple SESSION_SECRET=local), puis initialisez le dépôt Git sur la branche main et faites le premier commit de tout le projet. Le fichier .env doit exister sur le disque mais ne doit PAS être suivi par Git.
    Afficher un indicegit init -b main, git add ., puis git commit -m "…". Si Git réclame une identité : git config user.name "Votre nom" et git config user.email "vous@exemple.ma".
    Voir la solution
    cd /root/souk-atlas && echo "SESSION_SECRET=local" > .env && git init -q -b main && git add . && git -c user.name="Etudiant Souk Atlas" -c user.email="etudiant@exemple.ma" commit -q -m "Initialisation du projet Souk Atlas"

    Vérification : cd /root/souk-atlas && test -f .env && git rev-parse --verify HEAD >/dev/null 2>&1 && test "$(git branch --show-current)" = main && git ls-files | grep -qx README.md && git ls-files | grep -qx .gitignore && git ls-files | grep -qx docs/BESOINS.md && ! git ls-files | grep -qx .env

Références officielles consultées : Penser en React — https://fr.react.dev/learn/thinking-in-react ; Express : l'exemple « Hello world » — https://expressjs.com/fr/5x/starter/hello-world/ ; PostgreSQL — Architectural Fundamentals — https://www.postgresql.org/docs/current/tutorial-arch.html ; GitHub Actions — Intégration continue — https://docs.github.com/fr/actions/get-started/continuous-integration. Texte original MasterLinux.