Aller au contenu principal

Architecture

Vue d'ensemble de la structure technique de HeartCo.

Sommaire

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 :

GroupeURLUsage
(admin)/admin/*Panel admin (challenge 2FA)
(examples)Templates démo (pas de route publique)
(legal)/cgu, /cgv, ...Pages légales
(marketing)/about, /showcasePages 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édureAccèsUsage
publicProcedureTout le mondePages publiques, contact, booking
protectedProcedureAuthentifié (tous rôles)Profil, portail client
staffProcedureAuthentifié, rôle ≠ CLIENTToutes les features internes
managerProcedureADMIN, DIRECTION, MANAGER, HRGestion d'équipe, RH
adminProcedureADMIN uniquementParamètres critiques
requirePermission("x:y")staffProcedure + permission RBACAccès granulaire
requireAnyPermission([...])staffProcedure + au moins 1 permissionAccè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 } ou import type { Foo }
  • Path alias : ~/ pour tous les imports depuis src/
  • Pas de any : utiliser unknown + type guards
  • Langue : noms de variables/types en anglais, textes UI en français

◀ Getting Started · Sommaire · Authentification ▶