Lesson 1 of 12 · Design
The Souk Atlas project: requirements, wireframes, architecture and Git repository
Objective
Lay the foundations of the common thread project of this course: Souk Atlas, a marketplace where Moroccan artisans sell rugs, pottery, leather goods and jewelry, and where customers pay by bank transfer. At the end of the lesson, you know what the application must do, what it looks like and how its three building blocks talk to each other, and you have a clean Git repository with no secrets in it.
Key points
- A full-stack project starts on paper: user stories, wireframes, and a list of what is out of scope.
- Souk Atlas has three building blocks: a React front end (the browser), a Node.js/Express API (the business rules) and a PostgreSQL database (the source of truth for the data).
- The browser never talks directly to the database: everything goes through the API, which validates and recalculates.
- A single Git repository (a "monorepo") with
api/,web/anddocs/is more than enough for a small team. - Secrets (
.env) never go into Git: you version a.env.exampletemplate instead.
1. What this course brings together
You learned the building blocks one by one in the other MasterLinux courses:
| Building block | Where did you learn it? | What we do with it here |
|---|---|---|
HTML, CSS, JavaScript, fetch |
Web course (lessons 2.x and 3.2) | the user interface and the API calls |
| Node.js, Express | Node.js course | the marketplace REST API |
| React | React course | the front end: catalog, cart, seller area |
| SQL, PostgreSQL | SQL course | the schema and the queries |
| Docker, Compose | Docker course (lessons 1.4, 2.4, 2.5, 3.3) | packaging and deployment |
| GitHub Actions | CI/CD course (lessons 1.2, 2.1, 2.2) | automated tests and builds |
This course does not explain these basics again: it shows how to make them work together on a real product, with the decisions a full-stack developer makes every day. When a concept has already been covered, we refer you to the relevant lesson.
2. The client and their needs
The client: a fictitious cooperative, "Souk Atlas SARL", based in Fès. It wants to help about fifty artisans from Fès, Safi, Marrakech and Essaouira sell online, without depending on a foreign platform that takes a large commission.
What we know about its users:
- buyers are mostly in Morocco, on their phones, and many do not have a bank card that can be used online;
- artisans are not IT specialists: their screen must be simple;
- the cooperative receives the transfers on its account, then pays the artisans.
This leads to the most structuring decision of the project: payment is made by bank transfer. The buyer places an order and receives the cooperative's RIB (bank account details) and a reference to copy into the transfer description; an administrator then matches the transfers received and marks the orders as "paid". Card payment will come in version 2.
3. User stories
A user story describes a need from the point of view of the person who has it, in one sentence: "As a role, I do something to get a benefit". It does not say how to code it.
| Role | Story | Priority |
|---|---|---|
| Buyer | As a buyer, I browse the catalog by category and I search for a product by its name | essential |
| Buyer | As a buyer, I fill a cart and I see the total in dirhams, delivery included | essential |
| Buyer | As a buyer, I place an order and I receive the reference to write on my transfer | essential |
| Buyer | As a buyer, I follow the status of my order (pending, paid, shipped) | essential |
| Seller | As a seller, I add, modify and remove my products | essential |
| Seller | As a seller, I see the paid orders and I mark them as shipped | essential |
| Admin | As an administrator, I mark an order as paid when the transfer arrives | essential |
| Buyer | As a buyer, I leave a review on a product | later |
Writing the priority column is as important as the rest: it defines the minimum viable product, what you deliver first.
And the out of scope list, written down in black and white, avoids endless discussions: card payment, native mobile application, messaging between buyer and seller, returns management. It does not mean "never", it means "not in this version".
In the lab, the requirements document
docs/BESOINS.mdis written in French: the stories start with "En tant qu'acheteur…" (As a buyer…) or "En tant que vendeur…" (As a seller…).
4. Wireframes
Before coding, you draw the screens. A pencil and paper are enough, or a tool such as Figma or Penpot. Here are the five screens of version 1, as "wireframe" mockups (the interface of Souk Atlas is in French):
┌─────────────────────────────────────┐ ┌─────────────────────────────────────┐
│ 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
The five screens are: 1. Catalog, 2. Product page, 3. Cart and delivery, 4. Confirmation (amount to transfer, RIB, transfer description, status "waiting for the transfer"), 5. Seller area (my products, my orders).
Wireframes reveal questions that text hides: do you need an account to order? (yes, to follow your order); is delivery free? (above 500 DH); are prices VAT-inclusive? (yes, as in all retail in Morocco; the 20% VAT is included and displayed for information).
Write these decisions down in docs/: in three months, nobody will remember them.
5. The architecture
Browser (phone, PC)
┌────────────────────────┐ HTTPS + JSON ┌──────────────────────────┐ SQL ┌──────────────┐
│ React front (Vite) │ ────────────────▶ │ Node.js / Express API │ ─────────▶ │ PostgreSQL │
│ catalog, cart, │ ◀──────────────── │ validation, prices, │ ◀───────── │ tables, │
│ seller area │ session cookie │ stock, sessions, orders │ │ constraints │
└────────────────────────┘ └──────────────────────────┘ └──────────────┘
static files served by nginx port 3000 (local) port 5432 (local)
Each building block has one responsibility:
- The front end displays and collects. It can calculate a total "for information", but it has no authority: a clever user can modify any calculation made in their browser.
- The API applies the rules: it reads the prices again from the database, checks the stock, controls who is allowed to do what, and refuses everything else with a clear error code.
- The database keeps the data and protects its consistency with constraints (a stock cannot be negative, an order always belongs to an existing buyer).
Why these technologies? Not because they are fashionable: React has a huge ecosystem and developers available in Morocco; Express is the most widespread and best-documented Node.js server; PostgreSQL offers solid transactions, which are essential as soon as you handle money and stock. Another team could have chosen something else; what matters is being able to justify your choice.
The React documentation website offers a method for breaking a user interface down into components from a wireframe ("Thinking in React"): this is exactly what we will do in level 3.
6. The Git repository
A single repository for the whole project:
souk-atlas/
├── README.md ← what the project is, how to run it
├── .gitignore ← node_modules/, .env, dist/…
├── .env.example ← the expected variables, WITHOUT secret values
├── compose.yaml ← (level 4) the complete stack
├── docs/
│ ├── BESOINS.md ← user stories, out of scope, decisions
│ ├── API.md ← (lesson 1.3) the API contract
│ └── maquettes/
├── api/ ← the Node.js back end
│ ├── package.json
│ ├── migrations/ ← (lesson 1.2) the SQL schema, versioned
│ ├── src/
│ └── test/
└── web/ ← the React front end
├── package.json
└── src/
Create it:
mkdir -p souk-atlas/{api/src,web/src,docs}
cd souk-atlas
touch api/src/.gitkeep web/src/.gitkeep # Git does not track empty folders
printf '%s\n' 'node_modules/' '.env' 'dist/' 'coverage/' '*.log' > .gitignore
git init -b main
git add .
git commit -m "Initialisation du projet Souk Atlas"
Secrets: .env and .env.example
The API will need a database address and a session secret. These values live in a .env file, which is different on each machine and never committed:
# .env.example (versioned: it documents what must be filled in)
NODE_ENV=development
PORT=3000
DATABASE_URL=postgres://souk:souk@localhost:5432/souk_atlas
SESSION_SECRET=
Each developer copies the template with cp .env.example .env, then fills in their own values. Check that it is really ignored:
git status --short # .env must NOT appear
git check-ignore -v .env # shows the .gitignore rule that ignores it
A password pushed to GitHub, even for one minute, must be considered compromised: you must change it. The Git history keeps everything.
How to work
For a small team: the main branch is always deliverable; each feature is developed on a branch (feature/panier), then reaches main through a pull request that is reviewed and tested automatically (lesson 4.2). Clear commit messages ("Add the delivery calculation") are better than a complicated convention that nobody follows.
7. The course plan
| Level | Lessons | What you produce |
|---|---|---|
| 1 Design | 1.1 to 1.3 | requirements, SQL schema, API contract |
| 2 Back end | 2.1 to 2.4 | the API: skeleton, catalog, accounts, orders |
| 3 Front end | 3.1 and 3.2 | the complete React front end |
| 4 Going to production | 4.1 to 4.3 | tests, containers, CI, deployment on a VPS |
The labs run in a Node.js container without Internet access: you cannot install Express, React or PostgreSQL there. So you will write the project's business building blocks (validation, cart calculation, transfer reference, HTTP router, SQL schema…) using only the modules built into Node.js, and each check runs your code. These building blocks are exactly the ones you will then plug into Express and React on your own machine.
Common pitfalls
- Coding before knowing what to code: without stories or wireframes, you discover the real questions (VAT-inclusive or not? account required?) in the middle of development, and you start again.
- Forgetting the out of scope list: each meeting adds "just one small feature", and the project never ships.
- Committing
.env: add.envto.gitignorebefore the firstgit add ., not after. - Trusting the front end: a total, a price or a role sent by the browser can be modified by anyone with the developer tools.
Lab
You create the skeleton of the Souk Atlas repository in /root/souk-atlas: the api/, web/, docs/ tree and a README; the requirements document with its user stories and its out of scope list; the protection of secrets (.gitignore and .env.example); and finally the Git repository on the main branch with a first commit, checking that a real .env file stays out of Git.
Quiz
- Why must the browser not send the price of a product to the API when the order is placed?
- What is the difference between
.envand.env.example? - What is the "out of scope" list in the requirements document for?
- Why does Souk Atlas use an order reference in the transfer description?
- A colleague pushed the real database password in a commit, then removed it in the next commit. Is the problem solved?
Answers
- Because anything that comes from the browser can be modified by the user. The API receives only product identifiers and quantities, then reads the prices again from the database.
.envcontains the real values (password, secret) for this machine and is never versioned;.env.exampleis versioned, lists the expected variables and contains no secret value.- It sets what will not be done in this version, to protect the deadline and avoid constant additions.
- So that the administrator can match each transfer received with the right order; the check digits (lesson 2.4) also detect typing errors.
- No: the Git history keeps the old commit. You must consider the password compromised and change it, then possibly clean up the history.