Architecture
Vue d'ensemble de la structure technique de HeartCo.
Schéma global
┌─────────────────────────────────────────────────────────┐
│ Client (Browser) │
│ Next.js App Router + React 19 │
└────────────────────────┬────────────────────────────────┘
│ tRPC (HTTP / WebSocket)
┌────────────────────────▼────────────────────────────────┐
│ Serveur Next.js │
│ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │
│ │ NextAuth │ │ tRPC │ │ API Routes │ │
│ │ v5 │ │ Routers │ │ (webhooks, crons) │ │
│ └────┬─────┘ └────┬─────┘ └────────┬───────────┘ │
│ │ │ │ │
│ ┌────▼──────────────▼──────────────────▼───────────┐ │
│ │ Prisma 7 (ORM) │ │
│ │ generated/prisma/ (client) │ │
│ └──────────────────────┬───────────────────────────┘ │
└─────────────────────────┼───────────────────────────────┘
│ SQL
┌─────────────────────────▼───────────────────────────────┐
│ Supabase PostgreSQL │
│ (pgBouncer pour le pooling) │
└─────────────────────────────────────────────────────────┘
Services externes
Stripe ───────── Paiements, abonnements, webhooks
Resend ───────── Envoi d'emails transactionnels
Mistral AI ───── Copilote IA, génération, analyse
Pusher ───────── Temps réel (chat, notifications)
Upstash Redis ── Cache, rate limiting, locks distribués
Bridge API ───── Connexion bancaire (agrégation)
Iopole ───────── E-facturation B2B (Factur-X)
Google/Microsoft OAuth + Calendar + Drive
Arborescence des dossiers
src/
├── app/ # Pages (Next.js App Router)
│ ├── (admin)/ # Panel d'administration
│ ├── (examples)/ # Templates d'exemple (dashboard, landing)
│ ├── (legal)/ # Pages légales (CGU, CGV, confidentialité)
│ ├── (marketing)/ # Pages marketing (about, showcase)
│ ├── (public)/ # Pages publiques (désabonnement)
│ ├── dashboard/ # Application SaaS principale
│ │ ├── agenda/ # Calendrier
│ │ ├── analytics/ # Tableaux de bord
│ │ ├── clients/ # Gestion clients
│ │ ├── copilote/ # Assistant IA
│ │ ├── crm/ # Pipeline commercial
│ │ ├── facturation/ # Factures
│ │ ├── devis/ # Devis
│ │ ├── comptabilite/ # Comptabilité
│ │ ├── equipe/ # Gestion d'équipe
│ │ ├── rh/ # Ressources humaines
│ │ ├── parametres/ # Paramètres
│ │ └── ... # 37 modules au total
│ ├── api/ # API Routes
│ │ ├── auth/ # NextAuth + routes auth custom
│ │ ├── cron/ # 11 tâches planifiées
│ │ ├── webhooks/ # Webhooks (Stripe, Iopole, Resend)
│ │ ├── trpc/ # Endpoint tRPC
│ │ └── ...
│ ├── login/ # Page de connexion
│ ├── register/ # Inscription
│ ├── onboarding/ # Onboarding post-inscription
│ └── portal/ # Portail client
│
├── components/ # Composants React
│ ├── ui/ # Primitives (shadcn/Radix)
│ ├── layout/ # Layout (sidebar, topbar)
│ ├── landing/ # Composants landing page
│ └── <feature>/ # Composants par feature
│
├── lib/ # Utilitaires et logique métier
│ ├── ai/ # Mistral AI (service, prompts, tools)
│ ├── config/ # Branding, configuration app
│ ├── emails/ # Templates email (Resend)
│ ├── freemium/ # Limites et guards freemium
│ ├── navigation/ # Configuration sidebar
│ ├── permissions/ # Matrice RBAC
│ ├── prisma-org-scope.ts # Isolation multi-tenant
│ ├── rate-limit.ts # Rate limiting (Redis)
│ ├── redis.ts # Client Upstash Redis
│ ├── stripe-plan.ts # Plans et pricing Stripe
│ └── utils.ts # cn(), helpers généraux
│
├── modules/ # Modules métier certifiés
│ ├── bridge/ # Intégration bancaire
│ ├── facturx/ # E-facturation (NE PAS MODIFIER)
│ └── iopole/ # E-facturation B2B (NE PAS MODIFIER)
│
├── server/ # Couche serveur
│ ├── api/
│ │ ├── root.ts # Registre de tous les routers
│ │ ├── trpc.ts # Procédures et middlewares
│ │ └── routers/ # ~75 routers tRPC
│ ├── auth/
│ │ └── config.ts # Configuration NextAuth v5
│ └── db.ts # Instance Prisma
│
└── styles/
└── globals.css # Tailwind v4 + tokens CSS
Path alias
HeartCo utilise le path alias ~/ qui pointe vers ./src/ :
// Au lieu de :
import { cn } from "../../../lib/utils";
// Écrire :
import { cn } from "~/lib/utils";Configuré dans tsconfig.json :
{
"compilerOptions": {
"paths": {
"~/*": ["./src/*"],
"generated/prisma": ["./generated/prisma"]
}
}
}Route Groups (App Router)
Next.js App Router utilise des route groups (dossiers entre parenthèses) pour organiser les pages sans affecter l'URL :
| Groupe | URL | Usage |
|---|---|---|
(admin) | /admin/* | Panel admin (challenge 2FA) |
(examples) | — | Templates démo (pas de route publique) |
(legal) | /cgu, /cgv, ... | Pages légales |
(marketing) | /about, /showcase | Pages marketing |
(public) | /unsubscribed, ... | Pages publiques sans auth |
dashboard | /dashboard/* | Application SaaS principale |
Procédures tRPC
Les routers tRPC utilisent des procédures avec des niveaux d'accès croissants :
| Procédure | Accès | Usage |
|---|---|---|
publicProcedure | Tout le monde | Pages publiques, contact, booking |
protectedProcedure | Authentifié (tous rôles) | Profil, portail client |
staffProcedure | Authentifié, rôle ≠ CLIENT | Toutes les features internes |
managerProcedure | ADMIN, DIRECTION, MANAGER, HR | Gestion d'équipe, RH |
adminProcedure | ADMIN uniquement | Paramètres critiques |
requirePermission("x:y") | staffProcedure + permission RBAC | Accès granulaire |
requireAnyPermission([...]) | staffProcedure + au moins 1 permission | Accès multi-permission |
Exemple d'utilisation
// Router facturation — nécessite la permission "facturation:create"
export const facturationRouter = createTRPCRouter({
create: requirePermission("facturation:create")
.input(createInvoiceSchema)
.mutation(async ({ ctx, input }) => {
const invoice = await ctx.orgDb.invoice.create({
data: {
...input,
organizationId: ctx.session.user.organizationId,
},
});
return invoice;
}),
});Routers tRPC
75 routers sont enregistrés dans src/server/api/root.ts :
search, permissions, facturation, clients, crm, organization, members, devis,
products, comptabilite, rh, onboarding, notesDefrais, workOrders, workReports,
suppliers, payslips, employeeProfiles, payslipTemplates, contributionRates,
ideas, mood, teams, notifications, freemium, marketplace, portal, recouvrement,
signatures, suggestions, reportTemplates, reports, conversations, messages,
calendars, calendarEvents, calendarPermissions, chatbot, itineraires, blog,
projets, analytics, timesheets, appointments, publicBooking, leaveTypes,
leaveBalances, publicHolidays, leavePolicy, recurringInvoices, facturx, iopole,
iso20022, settings, dashboard, okrs, trial, marketing, adminEmail,
userPreferences, automation, deliveryNotes, bank, tickets, timeLogs, stock,
pushTokens, socialContent, regulatoryAssistant, copilote, testMode, betaCode,
adminPromoCode, contactForm
Conventions TypeScript
- Strict mode activé avec
noUncheckedIndexedAccess: true - Type imports obligatoires :
import { type Foo }ouimport type { Foo } - Path alias :
~/pour tous les imports depuissrc/ - Pas de
any: utiliserunknown+ type guards - Langue : noms de variables/types en anglais, textes UI en français