Retour aux projets

4Korners Member Portal

Une plateforme d'adhésion en production pour un organisme à but non lucratif de Montréal : inscription et connexion, adhésions Stripe, dons, catalogue d'activités et back-office admin. Je l'ai construite et je l'exploite seul, de la base de données au pipeline de déploiement.

Architecture

MembresPortail Next.jsPostgres
Paiements via Stripe et Zeffy. CRM synchronisé depuis Airtable via un cache de lecture quotidien.

Une application Next.js adossée à Postgres avec Drizzle. Elle se synchronise avec le CRM Airtable de l'organisme via un cache de lecture rafraîchi chaque jour, encaisse les paiements via Stripe et les dons via Zeffy, et protège chaque écran d'administration par un contrôle d'accès basé sur les rôles.

Décisions clés

Un cache SQL plutôt que des appels Airtable en direct

La limite de débit de l'API Airtable ne pouvait pas servir le portail directement. Je copie les données du CRM, qui changent peu, dans Postgres une fois par jour et je lis à partir de là : les pages destinées aux membres restent rapides et n'atteignent jamais la limite.

Un statut d'adhésion dérivé, calculé et non stocké

Le fait qu'un membre soit actif, expiré ou en délai de grâce est calculé à partir des paiements à la lecture, et non stocké sous forme d'indicateur. Une seule source de vérité, et aucun statut périmé à réconcilier.

Le point difficile

Les scanners de courriel brûlaient les liens à usage unique

Les scanners de sécurité des courriels préchargent les liens pour les vérifier. Ils ouvraient le lien de confirmation avant l'utilisateur et consommaient le jeton à usage unique, faisant échouer de vraies inscriptions. La solution : ne plus traiter un simple GET comme une confirmation et exiger une action explicite de l'utilisateur.

Sécurité et performance

  • L'authentification à deux facteurs pour l'admin (TOTP avec codes de secours) protège tout écran affichant des données personnelles.
  • Les points d'accès de connexion et de courriel sont limités en débit, et les server actions de production sont verrouillées à leur origine.
  • Conformité à la Loi 25 : les consentements sont recueillis à l'inscription, et une demande d'effacement est honorée à la fois dans le portail et le CRM.

Stack

Next.js 15TypeScriptPostgreSQLDrizzle ORMAuth.js v5StripeZeffyDockerGitHub Actions