Vue d’ensemble de Remix, NestJS, Prisma, Socket.io, Stripe, AWS S3 et Tailwind. Pourquoi ce choix ?
Dans ce premier chapitre, on présente la stack et l’architecture fullstack de notre chat temps réel.
Tu vas comprendre comment Remix gère le frontend, comment NestJS structure le backend, et comment tous les services (Socket.io, Prisma, AWS S3, Stripe) s’imbriquent.
Cette leçon sert de carte routière :
Prêt à embarquer ?
Voici les briques que tu vas utiliser :
Cette stack fullstack est conçue pour être modulable et maintenable.
Remix gère :
app/routes/
Structure typique :
1frontend/2├── app/3│ ├── components/4│ ├── hooks/5│ ├── routes/6│ │ ├── login.tsx7│ │ ├── chat.tsx8│ │ └── api.messages.ts9│ └── utils/10└── remix.config.js
NestJS s’appuie sur des modules pour séparer les domaines :
1backend/2├── src/3│ ├── auth/ # module Auth (JWT, Passport)4│ ├── chat/ # Gateway Socket.io + services5│ ├── prisma/ # PrismaModule + service6│ ├── s3/ # S3Module + service7│ ├── payments/ # StripeModule + Webhooks8│ └── main.ts9└── nest-cli.json
Chaque module regroupe :
Les Guards de NestJS protègent tes routes en vérifiant le JWT.
On utilise un Gateway Socket.io :
1import {2SubscribeMessage,3WebSocketGateway,4WebSocketServer,5} from '@nestjs/websockets' // ^? décorateurs WebSocket6// @callout: WebSocketGateway initialise le serveur Socket.io7@WebSocketGateway({ cors: { origin: '*' } })8export class ChatGateway {9@WebSocketServer()10server; // ^? instance Socket.io1112@SubscribeMessage('message')13handleMessage(client, payload) {14this.server.emit('message', payload)15}16}
Prisma simplifie la gestion de la base :
1datasource db { provider = "postgresql" url = env("DATABASE_URL") }2generator client { provider = "prisma-client-js" }34model User {5id String @id @default(cuid())6email String @unique7password String8avatarUrl String?9chats Chat[] @relation("user_chats")10}
Le PrismaModule exporte un PrismaService
injectable partout.
Le module S3 encapsule le SDK AWS :
1import { Injectable } from '@nestjs/common'2import { S3 } from 'aws-sdk' // ^? client S33@Injectable()4export class S3Service {5private s3 = new S3()6async upload(file: Express.Multer.File) {7// @callout: génère une URL signée pour sécuriser l’upload8return this.s3.upload({ Bucket: 'chat-avatars', Key: file.originalname, Body: file.buffer }).promise()9}10}
Le module Payments crée des sessions Stripe et gère les webhooks :
1import Stripe from 'stripe' // ^? SDK Stripe2export class PaymentsService {3private stripe = new Stripe(process.env.STRIPE_KEY, { apiVersion: '2022-11-15' })4createCheckout(userId: string) { /* ... */ }5}
1.2├── backend/3│ ├── src/4│ ├── package.json5│ └── tsconfig.json6├── frontend/7│ ├── app/8│ ├── remix.config.js9│ ├── package.json10│ └── tsconfig.json11├── prisma/12│ ├── schema.prisma13│ └── migrations/14└── docker-compose.yml
docker-compose.yml
orchestre Postgres et Redis (pour Socket.io Adapter).tsconfig.json
et ses scripts npm.Crée un .env
à la racine :
1DATABASE_URL=postgresql://user:pass@localhost:5432/chat2JWT_SECRET=tonSuperSecretJWT3AWS_ACCESS_KEY_ID=...4AWS_SECRET_ACCESS_KEY=...5STRIPE_KEY=...
1# installer frontend et backend2cd frontend && npm install3cd ../backend && npm install
1docker-compose up -d2cd backend && npm run start:dev3cd frontend && npm run dev
Chaque workspace dispose de ses règles ESLint/Prettier. On peut partager une config racine via eslint --ext .ts,.tsx .
.
Dessine ton architecture
Sur un schéma, dessine les communications entre Remix, NestJS, Prisma, Socket.io et AWS S3.
Crée un module NestJS
Initialise un module Notifications
avec son service et son controller.
Loader Remix
Dans app/routes/chat.tsx
, écris un loader qui appelle /api/messages
et retourne la liste de messages pour l’affichage.
Bonne pratique ! Tu as maintenant une vision claire de ton projet fullstack. On passe à la mise en place concrète dans la prochaine leçon.