Aller au contenu principal
AnthemionAnthemion
Retour aux projets

LADTC

Site WordPress lourd à maintenir pour un club de trail belge. Remplacé par une application Next.js auto-hébergée — blog intégré, gestion des membres, commandes d'équipement, événements, zéro CMS externe.

Développeur full-stack4 moisEn production
Next.jsPrismaPostgreSQLCoolifySelf-hostedDocker
21 avril 2026
4Rôles RBAC
14Modèles Prisma
8Modules livrés
Coolify (homelab)Déploiement
https://ladtc.be
LADTC

Problème

Le club LADTC (Ellezelles, Belgique) s'appuyait sur un site WordPress difficile à maintenir : plugins à mettre à jour, performance médiocre, contenu éditorial figé. Les besoins du comité débordaient du cadre CMS : gestion des membres, suivi des cotisations, commandes d'équipement, inscriptions aux événements, espace documents interne. Chaque fonction ajoutée via un plugin tiers multipliait les points de fragilité.

Solution

Remplacement complet par une application Next.js 16 auto-hébergée sur un homelab personnel. Blog intégré directement dans la base de données (plus de CMS externe), authentification email avec rôles, modules fonctionnels codés sur mesure. Déploiement par git push vers un serveur Coolify, exposition sécurisée via Cloudflare Tunnel sans ouvrir le moindre port.

Architecture

GitHub (push master)
      │ webhook
   Coolify (UM880 Pro, homelab)
   ├── Build Docker multi-stage
   ├── Entrypoint → migrations Prisma auto
   └── Runner slim Next.js
             │
   Cloudflare Tunnel (zéro port ouvert)
             │
      PostgreSQL 15 (même hôte, Docker)
             │
      Sentry + Uptime Kuma

Le pipeline push → build → migrations → start est entièrement automatique. L'entrypoint Docker charge le CLI Prisma depuis un répertoire isolé (/prisma-cli) pour éviter les conflits avec les node_modules du runner slim.

Stack technique

ComposantTechnologie
FrontendNext.js 16 (App Router), React 19, TypeScript 5.7
UITailwind CSS v4 + shadcn/ui
Data clientTanStack Query (staleTime + invalidation, pas de polling)
ORMPrisma 7
Base de donnéesPostgreSQL 15 (Docker)
AuthBetterAuth (email/password, RBAC : MEMBER, COACH, COMMITTEE, ADMIN)
EmailResend (SPF + DKIM + DMARC p=quarantine)
MonitoringSentry (client + server, DSN public au build) + Uptime Kuma
HébergementCoolify (self-hosted Docker)
Reverse proxyCloudflare Tunnel → Traefik

Modules livrés

  • Blog : CRUD admin, rendu Markdown, intégré à la base (plus de dépendance WordPress)
  • Membres : profils, statut cotisation, historique
  • Commandes équipement : catalogue, panier, checkout
  • Événements : création, inscriptions, suivi
  • Galerie photos : administration, affichage public
  • Documents internes : upload, notes associées, catégorisation
  • Pages statiques : accueil, équipe, contact
  • Admin : tableau de bord unifié pour le comité

Résultats

  • Migrations automatiques : l'entrypoint Docker applique les migrations Prisma à chaque déploiement, sans intervention manuelle
  • Email conforme : trio SPF/DKIM/DMARC configuré, passage progressif p=none → p=quarantine, rapports agrégés vers une boîte dédiée
  • Monitoring opérationnel : instrumentation Sentry client + serveur, compatible Turbopack via instrumentation-client.ts
  • Sécurité réseau : aucun port exposé sur la box, traversée Cloudflare Tunnel uniquement
  • Zéro coût d'hébergement : tout tourne sur le homelab, seul le domaine reste payant

Ce que j'ai appris

  • Construire un pipeline CI/CD self-hosted fiable (webhook GitHub → Coolify → build Docker → migrations → redémarrage)
  • Embarquer un CLI Prisma dans un runner Docker slim sans casser le node_modules applicatif
  • Contourner la spécificité Turbopack sur Next.js 16 : sentry.client.config.ts n'est pas bundlé, il faut basculer sur instrumentation-client.ts
  • Configurer une authentification stricte avec rôles sans dépendre d'un service externe (BetterAuth)
  • Maîtriser la chaîne email transactionnelle complète (SPF, DKIM, DMARC, Resend, OVH MX)
  • Exposer une application en production sans ouvrir de port grâce à Cloudflare Tunnel