Architecture
Vue d'ensemble de la structure technique de HeartCo.
Sommaire
- Schéma global
- Arborescence des dossiers
- Path alias
- Route Groups (App Router)
- Procédures tRPC
- Routers tRPC
- Conventions TypeScript
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
│ │ └── ... # 39 modules au total
│ ├── api/ # API Routes
│ │ ├── auth/ # NextAuth + routes auth custom
│ │ ├── cron/ # 18 tâches planifiées (QStash)
│ │ ├── 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/ # 76 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
76 routers sont enregistrés dans apps/web/src/server/api/root.ts :
adminEmail, adminPromoCodes, analytics, appointments, automation, bank,
betaCode, blog, calendarEvents, calendarPermissions, calendars, chatbot,
clients, comptabilite, contactForm, contributionRates, conversations,
copilote, crm, dashboard, deliveryNotes, devis, dunning, employeeProfiles,
facturation, facturx, freemium, ideas, iopole, iso20022, itineraires,
leaveBalances, leavePolicy, leaveTypes, marketing, marketplace, members,
messages, mood, notesdefrais, notifications, okrs, onboarding, organization,
payslips, payslipTemplates, permissions, portal, products, projets,
publicBooking, publicHolidays, pushTokens, recouvrement, recurringInvoices,
regulatoryAssistant, relances, reports, reportTemplates, rh, search,
settings, signatures, socialContent, stock, suggestions, suppliers, teams,
testMode, tickets, timeLogs, timesheets, trial, userPreferences, workorders,
workreports
Note : 2 routers (
adminEmail,adminPromoCodes) sont retirés du repo client lors de l'export — l'acheteur en voit donc 74.
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