- TypeScript 98.9%
- CSS 0.8%
- JavaScript 0.3%
- POST: le manager retourne { ticket: { reference, accessKey } },
pas { reference, accessKey } directement
- GET detail: les messages sont dans ticket.messages, pas à côté
- Séparer les erreurs réseau vs erreurs locales pour éviter
les doublons de tickets côté manager
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|---|---|---|
| prisma | ||
| scripts | ||
| src | ||
| tests | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| DEPLOY.md | ||
| DEPLOYMENT.md | ||
| eslint.config.mjs | ||
| next.config.mjs | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| PRODUCT.md | ||
| README.md | ||
| sentry.client.config.ts | ||
| sentry.edge.config.ts | ||
| sentry.server.config.ts | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
Kivora Beauty
Solution SaaS de réservation en ligne pour instituts de beauté, salons de coiffure, barbiers, spas, ongleries et professionnels indépendants.
Chaque déploiement héberge un établissement (modèle Kivora : 1 client = 1 base SQLite), provisionné et piloté depuis le manager Kivora.
Stack
- Next.js 16 (App Router, React 19) et TypeScript
- Prisma 5 + SQLite (
DATABASE_URL = file:/opt/clients/<slug>/dev.db) - Tailwind CSS 3
- Sessions par cookie HttpOnly, révocables, stockées hachées en base
- Mots de passe hachés avec scrypt (module
crypto, sans dépendance) - Emails via SMTP / Resend (
nodemailer)
Les « enums » du domaine sont des String en base, dont les valeurs autorisées sont
garanties par les unions TypeScript de src/lib/types.ts.
Les trois interfaces
| Interface | Routes | Rôle |
|---|---|---|
| Publique | /, /reserver, /rdv/[token] |
Présentation, réservation en ligne (mobile-first), gestion sans mot de passe par lien email |
| Espace client | /compte |
Rendez-vous, fidélité, récompenses, avis, coordonnées, consentements, export/suppression RGPD |
| Back-office pro | /pro, /pro/agenda, /pro/clients, /pro/avis, /pro/statistiques |
Tableau de bord, agenda, cycle de vie des rendez-vous, modération des avis, statistiques |
Rôles
OWNER (accès total) · MANAGER (agenda, équipe, clients, stats, config) ·
EMPLOYEE (son planning) · client final (ses propres informations). Les clients
finaux sont gratuits et illimités.
Cycle de vie d'un rendez-vous
En attente → Confirmé → Arrivé → En cours → Terminé (+ Annulé, Absence).
Les transitions autorisées sont définies dans APPOINTMENT_TRANSITIONS.
La clôture en Terminé déclenche, de manière idempotente (completeAppointment) :
attribution des points de fidélité, mise à disposition des statistiques, éligibilité
à la demande d'avis, et calcul du solde restant. Les points ne sont attribués
qu'après une prestation terminée.
Logique métier testée
src/lib/slots.ts— moteur de calcul des créneaux (horaires, pauses, buffers, collisions, « sans préférence » multi-prestataires). Pur, sans I/O.src/lib/availability.ts— passe de la base au moteur (fuseau horaire viadate-fns-tz).src/lib/booking.ts— création / modification / annulation avec garde anti-double-réservation transactionnelle et respect des règles d'annulation.src/lib/lifecycle.ts— transitions de statut et clôture idempotente.src/lib/loyalty.ts,src/lib/analytics.ts— fidélité et statistiques.
npm test # 17 tests (moteur de créneaux, fidélité, transitions, clôture idempotente)
Démarrage local
cp .env.example .env
npm install
npm run prisma:migrate # crée la base et applique les migrations
npm run db:seed # données de démonstration (Institut Lumière)
npm run dev
Comptes de démonstration :
- Pro :
proprietaire@institut-demo.fr/Demo1234!(le seed litBOOTSTRAP_*) - Client :
sophie@example.fr/Client1234!
Intégration au manager Kivora
Le manager provisionne chaque instance en écrivant /opt/clients/<slug>/.env
(voir manager/lib/deploy.ts). Beauty consomme ces variables via
src/lib/env.ts et amorce l'établissement + le compte
propriétaire de façon idempotente au déploiement :
npm run prisma:deploy && npm run bootstrap
bootstrap (script scripts/bootstrap.ts) ne crée jamais
de doublon et n'écrase aucune donnée existante.
Variables clés injectées : DATABASE_URL, SESSION_SECRET, BOOTSTRAP_ADMIN_EMAIL,
BOOTSTRAP_ADMIN_NAME, BOOTSTRAP_PASSWORD, BUSINESS_*, NEXT_PUBLIC_KIVORA_CATEGORY=beauty,
KIVORA_DEPLOYMENT_MODE (DEMO pendant l'essai), KIVORA_MANAGER_TOKEN (API interne signée),
PORT.
Voir DEPLOYMENT.md pour les détails et l'ajout de la catégorie
beauty côté manager.
Sécurité & RGPD
- Validation systématique côté serveur, limitation de débit sur les routes sensibles.
- Sessions révocables (déconnexion, changement d'identifiants, propagation manager).
- Journal d'audit des actions sensibles (
src/lib/audit.ts). - Export et suppression (anonymisation) des données client, historique des consentements.
- Aucun mot de passe n'est jamais renvoyé par email après sa création initiale.