cascadheure est une plateforme de mise en relation entre clients et prestataires de services locaux (ménage, électricité, plomberie, architecture, tech, bien-être, etc.). Elle couvre l’intégralité du cycle de vie d’une mission : inscription, demande de service, validation admin, assignation prestataire, paiement en deux temps (acompte 50 % + solde 50 %) via mobile money, et notifications en temps réel.
Le projet est organisé en monorepo avec Turborepo et pnpm workspaces.
| Couche | Technologies |
|---|---|
| Monorepo | Turborepo, pnpm workspaces |
| Backend | NestJS 11, TypeScript, Prisma 7, PostgreSQL |
| Frontend | Next.js 15 (App Router), React 19, TypeScript |
| UI | Tailwind CSS, Framer Motion, Lucide React, Recharts |
| Auth | JWT (Passport), OTP via Redis (mock en mémoire) |
Brevo (@getbrevo/brevo) |
|
| Paiements | Mbiyo Pay (mobile money RDC) |
| Temps réel | Socket.IO (notifications) |
| Validation | class-validator (backend), Zod + React Hook Form (frontend) |
┌─────────────────────────────────────────────────────────────────┐
│ apps/frontend │
│ Next.js 15 — Port 3000 │
│ Landing │ Auth │ Client │ Dashboard Provider │ Admin │
└──────────────────────────┬──────────────────────────────────────┘
│ REST (Axios) + WebSocket
▼
┌─────────────────────────────────────────────────────────────────┐
│ apps/backend │
│ NestJS — Port 4000 — Préfixe /api/v1 │
│ Auth │ Users │ Services │ Requests │ Providers │ Payments │
│ Notifications │ Admin │ Uploads │
└──────────┬──────────────────────────────┬───────────────────────┘
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ PostgreSQL │ │ Redis (OTP) │
│ (Prisma) │ │ docker/local │
└───────────────┘ └───────────────┘
| Module | Responsabilité |
|---|---|
auth |
Inscription, OTP, login, refresh, reset password |
users |
CRUD utilisateurs (admin) |
services |
Catalogue de prestations |
requests |
Demandes clients + validation admin |
providers |
Candidatures, missions, profil prestataire |
payments |
Acompte/final Mbiyo Pay + webhook |
notifications |
Persistance + WebSocket temps réel |
admin |
Dashboard, analytics, financials |
uploads |
Fichiers statiques (/uploads/) |
mail |
E-mails transactionnels Brevo |
redis |
Stockage OTP/tokens temporaires |
cascadheure/
├── apps/
│ ├── backend/ # API NestJS (@cascadheure/backend)
│ │ ├── prisma/
│ │ │ ├── schema.prisma # Schéma de données
│ │ │ ├── seed.ts # Données de test
│ │ │ └── migrations/
│ │ ├── src/
│ │ │ ├── auth/
│ │ │ ├── users/
│ │ │ ├── services/
│ │ │ ├── requests/
│ │ │ ├── providers/
│ │ │ ├── payments/
│ │ │ ├── notifications/
│ │ │ ├── admin/
│ │ │ ├── uploads/
│ │ │ ├── mail/
│ │ │ └── redis/
│ │ ├── http/ # Fichiers .http pour REST Client
│ │ └── docker-compose.yml # PostgreSQL + Redis local
│ │
│ └── frontend/ # App Next.js (@cascadheure/frontend)
│ ├── src/
│ │ ├── app/ # Routes App Router
│ │ ├── components/ # auth/, landing/, admin/
│ │ └── lib/ # api.ts, auth-context, guards
│ └── prisma/ # Schéma Prisma (legacy, peu utilisé)
│
├── packages/ # Réservé aux libs partagées (vide)
├── .env.example # Variables d'environnement
├── render.yaml # Config déploiement Render
├── turbo.json # Orchestration Turborepo
├── pnpm-workspace.yaml
└── package.json
corepack enable recommandé)# Cloner le dépôt
git clone <url-du-repo>
cd cascadheure
# Installer les dépendances (à la racine)
pnpm install
Copiez le fichier d’exemple et renseignez vos valeurs :
cp .env.example .env
| Variable | Description | Exemple |
|---|---|---|
DATABASE_URL |
Connexion PostgreSQL | postgresql://user:pass@localhost:5432/cascadheure_db |
PORT |
Port backend | 4000 |
FRONTEND_URL |
URL(s) frontend autorisées (CORS) | http://localhost:3000 |
JWT_ACCESS_SECRET |
Secret JWT access token | Chaîne aléatoire forte |
JWT_REFRESH_SECRET |
Secret JWT refresh token | Chaîne aléatoire forte |
BREVO_API_KEY |
Clé API Brevo (e-mails) | — |
MAIL_FROM_EMAIL |
Expéditeur e-mails | contact@cascadheure.com |
MAIL_FROM_NAME |
Nom expéditeur | L'équipe cascadheure |
MBIYO_API_URL |
URL API Mbiyo Pay | https://dashboard.mbiyo.africa/api/v1 |
MBIYO_SECRET_KEY |
Clé API marchande Mbiyo (test ou production) | — |
MBIYO_WEBHOOK_SECRET |
Secret webhook HMAC | — |
MBIYO_WEBHOOK_URL |
URL callback webhook | https://api.example.com/api/v1/payments/webhook/mbiyo |
NEXT_PUBLIC_API_URL |
URL API pour le frontend | http://localhost:4000/api/v1 |
Note : Le frontend lit
NEXT_PUBLIC_API_URL. Placez-la dansapps/frontend/.env.localou à la racine selon votre setup.
cd apps/backend
docker compose up -d
Services démarrés :
localhost:5432 (user: admin_cascadheure, pass: 1234567890, db: cascadheure_db)localhost:6379http://localhost:8081Utilisez Neon, Supabase, Render PostgreSQL, etc. et renseignez DATABASE_URL.
# Générer le client Prisma
pnpm --filter @cascadheure/backend exec prisma generate
# Appliquer les migrations
pnpm --filter @cascadheure/backend exec prisma migrate dev
# Peupler la base avec des comptes de test
pnpm --filter @cascadheure/backend exec prisma db seed
pnpm dev
Démarre simultanément :
# Backend uniquement
pnpm backend:dev
# Frontend uniquement
pnpm frontend:dev
pnpm build
pnpm start
Après prisma db seed, les comptes suivants sont disponibles (mot de passe : password123) :
| Rôle | Téléphone | |
|---|---|---|
| ADMIN | cascadheure@gmail.com |
+243990000000 |
| CLIENT | client@gmail.com |
+243990000001 |
| PROVIDER | provider@gmail.com |
+243990000002 |
Les comptes ADMIN ne peuvent pas être créés via l’API d’inscription — ils doivent être insérés via le seed ou directement en base.
/) ou /services/mes-demandes/devenir-prestataire/dashboard/admin/dashboardPENDING ──(admin approuve)──► APPROVED
│ │
│(admin rejette) │(prestataire accepte)
▼ ▼
REJECTED ACCEPTED
│
(client paie acompte 50%)
▼
IN_PROGRESS
│
(prestataire termine)
▼
AWAITING_FINAL
│
(client paie solde 50%)
▼
COMPLETED
| Statut | Signification |
|---|---|
PENDING |
Demande créée, en attente de validation admin |
APPROVED |
Admin a validé et fixé le prix |
REJECTED |
Demande refusée par l’admin |
ACCEPTED |
Prestataire a accepté, en attente de l’acompte |
IN_PROGRESS |
Acompte versé, mission en cours |
AWAITING_FINAL |
Mission terminée, en attente du paiement final |
COMPLETED |
Mission clôturée |
Base URL : http://localhost:4000/api/v1
/auth)| Méthode | Route | Accès | Description |
|---|---|---|---|
| POST | /auth/register |
Public | Inscription + envoi OTP |
| POST | /auth/verify-otp |
Public | Vérification du compte |
| POST | /auth/resend-otp |
Public | Renvoi du code OTP |
| POST | /auth/login |
Public | Connexion (access + refresh tokens) |
| POST | /auth/refresh |
Refresh token | Renouvellement des tokens |
| GET | /auth/me |
JWT | Profil connecté |
| PATCH | /auth/me |
JWT | Mise à jour du profil |
| POST | /auth/logout |
Refresh token | Déconnexion |
| POST | /auth/forgot-password |
Public | Demande de reset |
| POST | /auth/reset-password |
Public | Réinitialisation |
/services)| Méthode | Route | Accès |
|---|---|---|
| GET | /services |
Public |
| GET | /services/:id |
Public |
| POST | /services |
ADMIN |
| PATCH | /services/:id |
ADMIN |
| DELETE | /services/:id |
ADMIN |
/requests)| Méthode | Route | Accès |
|---|---|---|
| POST | /requests |
CLIENT |
| GET | /requests |
CLIENT |
| GET | /requests/availability/:serviceId |
Public |
| GET | /requests/:id |
CLIENT |
| PATCH | /requests/:id |
CLIENT |
| DELETE | /requests/:id |
CLIENT |
/provider, /providers)| Méthode | Route | Accès |
|---|---|---|
| POST | /providers/apply |
JWT |
| GET | /providers/my-application |
JWT |
| GET | /provider/dashboard-stats |
PROVIDER |
| GET | /provider/my-missions |
PROVIDER |
| GET | /provider/requests |
PROVIDER |
| PATCH | /provider/requests/:id/accept |
PROVIDER |
| PATCH | /provider/requests/:id/complete |
PROVIDER |
| GET/PATCH | /provider/profile |
PROVIDER |
/payments)| Méthode | Route | Accès |
|---|---|---|
| POST | /payments/initiate/deposit |
CLIENT |
| POST | /payments/initiate/final |
CLIENT |
| POST | /payments/webhook/mbiyo |
Public (HMAC) |
| GET | /payments/status/:paymentId |
CLIENT |
/admin)| Méthode | Route | Description |
|---|---|---|
| GET | /admin/dashboard |
Données agrégées |
| GET | /admin/dashboard/stats |
Statistiques |
| GET | /admin/users |
Liste utilisateurs |
| GET | /admin/requests |
Liste demandes |
| PATCH | /admin/requests/:id/approve |
Approuver |
| PATCH | /admin/requests/:id/reject |
Rejeter |
| GET | /admin/providers/applications |
Candidatures |
| GET | /admin/financials |
Données financières |
| GET | /admin/analytics |
Analytiques |
/notifications)| Méthode | Route | Description |
|---|---|---|
| GET | /notifications |
Liste paginée |
| GET | /notifications/unread-count |
Compteur non-lues |
| PATCH | /notifications/read-all |
Tout marquer lu |
| PATCH | /notifications/:id/read |
Marquer une notification |
/uploads)| Méthode | Route | Description |
|---|---|---|
| POST | /uploads/avatar |
Image profil (max 5 Mo) |
| POST | /uploads/service |
Image service (max 5 Mo) |
Documentation détaillée des tests manuels :
apps/backend/http/README.md
| Route | Description |
|——-|————-|
| / | Page d’accueil (landing) |
| /services | Catalogue de services |
| /login | Connexion |
| /register | Inscription |
| /verify-otp | Vérification OTP |
| /forgot-password | Mot de passe oublié |
| /reset-password | Réinitialisation |
| Route | Description |
|——-|————-|
| /mes-demandes | Suivi des demandes |
| /notifications | Notifications |
| /client/profil | Profil client |
| /devenir-prestataire | Candidature prestataire |
| /parametres/* | Sécurité, notifications, suppression |
/dashboard)| Route | Description |
|——-|————-|
| /dashboard | Tableau de bord |
| /dashboard/missions | Missions disponibles |
| /dashboard/mes-missions | Missions acceptées |
| /dashboard/calendrier | Calendrier |
| /dashboard/profil | Profil prestataire |
| /dashboard/notifications | Notifications |
/admin)| Route | Description |
|——-|————-|
| /admin/dashboard | Vue d’ensemble |
| /admin/client | Gestion clients |
| /admin/prestataire | Candidatures prestataires |
| /admin/service | CRUD services |
| /admin/request | Gestion demandes |
| /admin/revenu | Revenus |
| /admin/financials | Finances |
| /admin/analytics | Analytiques |
| /admin/users | Utilisateurs |
| /admin/settings | Paramètres |
pnpm --filter @cascadheure/backend test
pnpm --filter @cascadheure/backend test:cov
pnpm --filter @cascadheure/backend test:e2e
.http dans apps/backend/http/ dans l’ordre indiquépnpm lint
pnpm format
Le fichier render.yaml configure le déploiement automatique :
# Build (Render)
pnpm run render:build
# Start (Render)
pnpm run render:start
Le build exécute : installation → prisma generate → prisma db push → compilation TypeScript.
apps/frontend sur VercelNEXT_PUBLIC_API_URL vers l’URL du backend RenderFRONTEND_URL côté backend avec l’URL Vercelopenssl rand -base64 32)FRONTEND_URL pour le CORS| Script | Description |
|---|---|
pnpm dev |
Démarre frontend + backend en mode watch |
pnpm build |
Build de toutes les apps |
pnpm start |
Démarre en mode production |
pnpm lint |
Lint de toutes les apps |
pnpm test |
Tests de toutes les apps |
pnpm format |
Formatage Prettier |
pnpm backend:dev |
Backend seul |
pnpm frontend:dev |
Frontend seul |
pnpm render:build |
Build pour Render |
pnpm render:start |
Start pour Render |
User ──┬── clientRequests (Request)
├── providerRequests (Request)
├── providerApplications (ProviderApplication)
├── services (Service) [prestataires assignés]
└── notifications (Notification)
Service ── requests (Request)
Request ── payments (Payment)
└── notifications (Notification)
ProviderApplication ── notifications (Notification)
Rôles : CLIENT, PROVIDER, ADMIN
Statuts prestataire : DISPONIBLE, EN_MISSION, INDISPONIBLE
Projet privé — tous droits réservés.