Commit Graph
31 Commits
Author SHA1 Message Date
Claude a52e13e623 Promotions : page publique dédiée, l'accueil garde les six dernières
`/promotions` liste toutes les offres en cours ; l'accueil en montre six et
renvoie vers elle. Les deux listes partagent `PromoCard`, extrait de la page
d'accueil : un seul rendu de carte à maintenir.

- `getLivePromotions(limit)` accepte `null` pour « toutes les offres », la
  limite restant appliquée en SQL et non après coup.
- Page complète : `<h1>` unique, `<main>`, métadonnées et canonique via
  `pageMetadata`, JSON-LD `BreadcrumbList` + `ItemList`, entrée au sitemap,
  état vide qui renvoie vers l'annuaire.
- Les liens « Promotions » de l'en-tête, du pied de page et de l'espace
  adhérent visent désormais cette page. Idem pour le lien d'une publication
  réseau sans adhérent rattaché, qui pointait sur l'ancre `/#promotions`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
2026-09-06 14:34:27 +00:00
Claude d99ee7ec07 Promotions : logo de l'adhérent dans l'angle des cartes
Le logo du commerce identifie l'offre avant même qu'on lise le nom. Il est
posé en pastille ronde dans l'angle haut-gauche de la carte, la catégorie se
décalant juste à côté sur la même ligne.

- `src/components/MemberAvatar.tsx` : logo en `contain` sur fond blanc (les
  logos d'adhérents sont des marques sur fond clair, un `cover` les rognerait),
  repli sur les initiales colorées quand la fiche n'a pas de logo.
- Appliqué à la carte d'accueil, à la carte de la fiche adhérent, à l'aperçu
  en direct de l'espace adhérent et à la carte de modération : même composition
  partout, l'aperçu montre donc bien ce que verra le visiteur.
- `getLivePromotions` remonte `members.logo_url` ; la page espace le passe au
  formulaire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
2026-09-06 14:02:53 +00:00
Claude 23d1d14a49 Espace adhérent en deux pages, e-mail de contact, logo sans débordement, types de produits pour les promos
- Espace adhérent : /backend/espace (profil, inscriptions, droit à l'image)
  et /backend/espace/promotions (dépôt et suivi). Bandeau et onglets communs
  (EspaceHeader) avec le nombre d'offres en ligne ; la page promotions ouvre
  sur « Mes promotions en cours », puis le formulaire, puis les offres en
  attente et l'historique. Deux entrées dans le menu, titres de page dédiés,
  revalidation des deux chemins.
- Fiche adhérent : colonne members.contact_email (migration 0013), saisie
  dans l'espace adhérent et la fiche staff ; la fiche publique et le JSON-LD
  affichent contact_email, sinon l'e-mail du compte.
- VitrineImage : sans photo de couverture, le logo est contenu à ~60 % d'un
  cadre à hauteur fixe sur un fond du logo flouté ; le conteneur sans hauteur
  qui laissait le logo déborder est supprimé.
- Promotions : la catégorie devient un type de produit ou de service
  (src/lib/promo-categories.ts, 10 groupes, ~85 entrées) pré-sélectionné
  depuis le métier de l'adhérent, à la place de la liste des métiers.
- Tests : catégories de promo (largeur, unicité, pré-sélection pour chaque
  métier du référentiel).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDbKbJrPWweXXYSxA8MXW7
2026-09-06 09:02:27 +00:00
Claude bfc82b3b3b Tags adhérents automatiques : vocabulaire par métier, suggestions et repli
- src/lib/tags.ts (pur) : mots-clés par métier pour les 104 catégories,
  vocabulaire transversal détecté dans la description (fait maison, bio,
  livraison, sur rendez-vous, devis gratuit…), suggestTags() qui combine
  métier, commune et description, autoTags() qui n'intervient qu'à vide.
- Enregistrement : addMember, updateMember et updateOwnProfile passent par
  resolveMemberTags() ; un champ laissé vide reçoit les suggestions, une
  saisie n'est jamais remplacée.
- Formulaires : composant TagsField (champ non contrôlé + pastilles de
  suggestions recalculées à chaque frappe depuis catégorie, commune et
  description ; « Tout ajouter »), dans l'espace adhérent et la fiche staff.
- Fiche publique : les fiches jamais ré-enregistrées affichent les tags
  suggérés et les transmettent dans LocalBusiness.keywords.
- tests/tags.test.ts : couverture de chaque métier, nettoyage, détection,
  ordre des suggestions, non-écrasement.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDbKbJrPWweXXYSxA8MXW7
2026-09-06 06:51:25 +00:00
Claude c8417d8560 SEO : URLs de fiche parlantes, pages métier indexables, aides de rédaction
- Fiches adhérents : URL canonique /adherents/12-au-bon-pain-frouard
  (memberPath). L'identifiant en tête suffit ; /adherents/12 et tout slug
  périmé sont redirigés de façon permanente vers la forme canonique, donc
  les anciens liens et les partages sociaux restent valides. Tous les liens
  (accueil, carrousel, annuaire, JSON-LD, sitemap, publications Facebook /
  LinkedIn) passent par memberPath.
- Pages métier /annuaire/[categorie] : une page indexable par catégorie
  avec titre, introduction (effectif, communes), grille d'adhérents, fil
  d'Ariane et ItemList. Sans adhérent : noindex et hors sitemap. Section
  « Parcourir par métier » sur l'annuaire et « Autres métiers » sur chaque
  page pour le maillage interne.
- Composants partagés MemberCard et CategoryLinks ; slugify déplacé dans
  src/lib/slug.ts.
- Backend : conseils de rédaction sous les champs description et tags des
  formulaires adhérent (espace adhérent et fiche staff).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDbKbJrPWweXXYSxA8MXW7
2026-09-06 06:29:28 +00:00
Claude f9d0d6c825 Accueil, pied de page et catégories : compteur réel, boutons alignés, référentiel complété
- Accueil : le bandeau « Faites partie de l'aventure » affiche le nombre
  d'adhérents validés (statut active) au lieu de « plus de 120 » codé en dur.
- Pied de page : les boutons Facebook / LinkedIn ont la même largeur (grille à
  une colonne dimensionnée sur le plus long) et une icône à largeur fixe.
- Catégories : référentiel unique dans src/db/categories.ts (104 métiers, dont
  assurance, bazar/discount, grande distribution, librairie-presse, tabac,
  vétérinaire, auto-école, etc.), inséré par la migration 0012 avec
  ON CONFLICT (slug) : les catégories manquantes apparaissent au prochain
  démarrage, sans écraser un libellé renommé depuis le backend. Le seed et
  l'action « Ajouter une catégorie » réutilisent ce référentiel et sa palette.
- tests/categories.test.ts vérifie unicité des slugs, contraintes de la table
  et cohérence entre le référentiel et la migration.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDbKbJrPWweXXYSxA8MXW7
2026-09-06 06:18:37 +00:00
Claude a8adb9ae6a Référencement : métadonnées complètes, données structurées, sitemap et robots
- Layout : metadataBase, gabarit de titre « %s · Plein R », description,
  mots-clés, Open Graph / Twitter, robots, icônes, manifeste, viewport et
  couleur de thème ; JSON-LD Organization + WebSite (recherche annuaire).
- Chaque page publique pose titre, description (≤ 160 caractères) et
  canonique via pageMetadata() ; l'annuaire ignore ainsi ?q=. Fiche adhérent :
  titre « Nom · Catégorie à Ville », description dérivée, LocalBusiness avec
  adresse, contacts et horaires (OpeningHoursSpecification), BreadcrumbList.
  Annuaire : ItemList des adhérents. Association : BusinessEvent par
  rencontre à venir. Rencontres passées : fil d'Ariane.
- Nouvelles routes : robots.txt, sitemap.xml (pages statiques + adhérents
  actifs), manifest.webmanifest, image de partage 1200×630 générée avec le
  logo, page 404 dédiée (noindex).
- /backend, /login, /inscription/* et les fiches inactives en noindex.
- Landmarks <main> sur toutes les pages publiques, fil d'Ariane en <nav>.
- serializeJsonLd() échappe <, > et & : les saisies des adhérents ne peuvent
  pas fermer le bloc <script>. Tests unitaires dans tests/seo.test.ts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDbKbJrPWweXXYSxA8MXW7
2026-09-05 10:41:53 +00:00
Claude 3b17d7ff42 Durcissement (lot A) : seed sûr en production, mots de passe temporaires affichés une seule fois
Audit de sécurité complet de l'application, puis correctifs du lot A validés :

- Seed : plus aucun compte de démonstration (mot de passe « changeme123 »)
  sans SEED_DEMO=true. L'administrateur initial reçoit un mot de passe
  aléatoire affiché une fois dans les journaux (ou SEED_ADMIN_PASSWORD) et
  doit le changer à la première connexion. docker-compose ne fournit plus de
  mot de passe par défaut.
- Mots de passe temporaires : la colonne users.temp_password (en clair) est
  supprimée (migration 0011). Création d'adhérent, réinitialisation,
  rattrapage des comptes manquants, approbation de demande et invitation
  staff renvoient les identifiants, affichés une seule fois par le composant
  OneTimeCredentials, sans redirection. L'invitation staff, qui ne
  communiquait jamais le mot de passe, redevient utilisable et impose le
  changement à la première connexion.
- Sessions JWT limitées à 7 jours (30 auparavant).
- En-têtes : Strict-Transport-Security ajouté, X-Powered-By supprimé.
- docker-compose : port Postgres publié sur 127.0.0.1 uniquement.
- Image Docker sur node:22 (Node 20 en fin de vie).
- Dépendances : next 15.5.25, pg 8.23, nanoid 3.3.18 (avis GHSA-2v37-7h3g-55p8).

Vérifié en local : tests, typage, build de production, migration + seed sur
un Postgres 16, et parcours navigateur complet (première connexion, changement
forcé, création / réinitialisation / invitation avec affichage unique, cookie
de session à 7 jours).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RAQsCp4nnZbwexCg7NDBHE
2026-09-04 09:15:45 +00:00
Claude dd7bbfb777 Refonte du pied de page
Trois colonnes dont une très large laissaient le tiers droit vide, les titres ne
se distinguaient pas des liens, et les deux icônes sociales flottaient en bas à
gauche sans rattachement.

- Quatre colonnes : marque, Accès rapide, Informations, Nous suivre. La largeur
  est enfin occupée, et la dernière colonne accueille aussi les coordonnées de
  l'association dès qu'elles sont renseignées dans Paramètres.
- Titres en capitales espacées sur le brun de la marque : ils reprennent le
  vocabulaire des pastilles utilisées partout ailleurs sur le site, et se lisent
  désormais comme des titres.
- Icônes sociales remplacées par des boutons libellés, calés à gauche pour ne
  pas s'étirer en pavés vides.
- Filet doré en haut du bloc, pastille dorée devant « Bassin de Pompey » : la
  page se referme au lieu de s'arrêter sur une ligne grise.
- Liens plus aérés, décalage léger au survol.
- Deux entrées utiles ajoutées : Rencontres passées et Espace adhérent.
- Replis : 3 colonnes sur tablette, 2 sur téléphone avec la marque et les
  réseaux sur toute la largeur.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
2026-07-25 13:11:29 +00:00
Claude db361051e6 Menu d'administration regroupé et version mobile du site
Le menu empilait douze liens sous un seul intitulé, avec des carrés, ronds et
losanges qui ne portaient aucun sens. Sur téléphone, la barre latérale se
dépliait en ligne et devenait un pavé de boutons inutilisable.

Navigation
- Six rubriques au lieu d'une pile : Pilotage, Vie du réseau, Rencontres,
  Communication, Configuration, Côté adhérent. Le quotidien est ainsi séparé de
  ce qu'on ne touche qu'occasionnellement.
- Une icône par entrée (`BackendIcons.tsx`) à la place des formes génériques.
- Le menu devient une table de données filtrée par capacité, au lieu de douze
  blocs JSX répétant les mêmes appels à `can()`.

Mobile
- Sous 1024px la barre latérale devient un tiroir : voile de fond, fermeture par
  Échap, par clic hors zone et à la navigation, défilement de la page bloqué,
  actions Voir le site / Déconnexion rapatriées dans le tiroir.
- `min-height: 0` sur la zone de navigation : sans lui l'enfant flex refusait de
  rétrécir et la carte utilisateur recouvrait les derniers liens, interceptant
  les clics.
- En-tête public repensé : logo toujours présent sur téléphone (seul retour à
  l'accueil), accès adhérent sur la même ligne, navigation répartie en dessous
  au lieu de se replier en escalier.
- Liste des adhérents : le tableau à cinq colonnes devient une fiche par
  adhérent, sur deux lignes constantes, sans défilement horizontal.
- Compteurs du tableau de bord en deux colonnes plutôt qu'empilés.

Vérifié : aucun débordement horizontal sur les 23 pages en 320, 390 et 768 px ;
tiroir et cibles tactiles testés au doigt sur toutes les interactions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
2026-07-25 00:25:56 +00:00
Claude e3a4771edf Refonte du bloc infos pratiques, suspension des promos et publication réseaux
Bloc « Informations pratiques » (fiche adhérent)
- Suppression des dégradés hors palette (radial doré de la section, dégradés
  crème/bleu des deux sous-cartes) au profit du vocabulaire visuel du site :
  carte blanche bordée, sous-cartes plates sur le fond de champ, variables CSS.
- La pastille « Préparer votre visite » devient une puce arrondie identique aux
  badges du reste du site ; le chip d'ouverture reprend les teintes de statut.
- Les glyphes texte ◷ et ↗ sont remplacés par des icônes SVG cohérentes.

Suspension des promotions
- Nouveau statut `suspended` + colonnes `suspended_by` / `suspended_by_id` /
  `suspended_at`.
- L'adhérent suspend et réactive ses propres promotions depuis Mon espace ;
  l'association suspend et réactive n'importe laquelle depuis le backoffice.
- Une suspension décidée par l'association ne peut pas être levée par
  l'adhérent : le motif est affiché dans son espace.
- Les lectures publiques filtrant déjà sur `live`, une promo suspendue quitte
  immédiatement l'accueil, l'annuaire et la fiche.

Publication Facebook / LinkedIn
- `src/lib/social.ts` : publication d'une promo en ligne sur la page Facebook
  (Graph API, upload multipart car les images sont en data-URI) et sur la page
  LinkedIn (Posts API + Images API en trois étapes).
- Jetons d'accès exclusivement en variables d'environnement ; un réseau non
  configuré masque son bouton.
- Table `social_posts` : chaque tentative est tracée, un échec est rattrapé et
  affiché sur la carte de la promo sans interrompre le backoffice.
- Nouvelle capacité RBAC `publishSocial` (admin + modérateur).

Liens sociaux publics
- Réglages `association_facebook` / `association_linkedin` éditables dans
  Paramètres, préremplis avec les pages de l'association.
- Section « Plein R sur les réseaux » sur l'accueil et icônes dans le pied de
  page, masquées si le réglage est vide.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
2026-07-24 22:20:51 +00:00
Michael dd9697019c Refonte des horaires et contacts adhérents 2026-07-23 16:22:28 +02:00
Michael 5e7233f98d polish meeting and consent views 2026-07-18 04:17:28 +02:00
Michael afc805c96a separate meetings and add member registrations 2026-07-18 03:56:54 +02:00
Michael b2d428b08b Add Plein R email composers 2026-07-17 19:53:42 +02:00
Michael 28ada88155 Add association meetings and GDPR settings 2026-07-17 17:47:24 +02:00
Michael b4c8967a3c Améliore les modales et les informations du site 2026-07-17 09:00:29 +02:00
Claude b0154d6fc1 Vitrine sans photo : logo encadré dans le thème (fini le fond blanc nu)
Quand un adhérent n'a pas de photo de couverture/vitrine, le logo était affiché
sur fond blanc brut. Il est désormais présenté dans une carte blanche encadrée
(bordure crème + ombre douce) sur fond crème dégradé — cohérent avec le thème.
S'applique à la fiche, l'annuaire et le carrousel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwfhYHzC9hQWPDnQ2p53GL
2026-06-28 06:47:08 +00:00
MichaelandClaude Opus 4.8 03eca6e9ae feat: adaptive promo images with blurred fill
Replace cover-crop background with PromoImage component: sharp
contain image over a blurred cover copy. Whole image visible on
any aspect ratio, no flat letterbox bars. Applied to accueil,
adherent profile, backend promotions, member space preview +
upload dropzone.

Also retheme adherent logo frame (cream gradient + warm border)
instead of flat white.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 14:59:46 +02:00
MichaelandClaude Opus 4.8 c199d7a7db Responsive mobile
- Anti-debordement horizontal global (overflow-x hidden, img max-width)
- Container : padding reduit a 16px sous 640px
- En-tete/pied de page : padding horizontal fluide (clamp), en-tete wrap
- Titres principaux en clamp() (accueil hero/h2, annuaire, fiche) pour
  ne plus deborder sur petit ecran
- Liste adherents du back-office : defilement horizontal (.table-scroll)
  au lieu de colonnes ecrasees

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 11:07:07 +02:00
MichaelandClaude Opus 4.8 497ea0562c Logo adaptatif (contain) dans le cadre du profil et les previews
- Avatar logo de la fiche adherent : <img> object-fit contain centre,
  cadre a overflow hidden -> plus de debordement quel que soit le ratio
- ImageField : prop fit (cover|contain). Champs logo en contain (apercu
  centre, non etire) dans l'edition fiche et l'espace adherent

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 11:03:37 +02:00
MichaelandClaude Opus 4.8 aa63462eff Logo en remplacement de la vitrine : centre et reduit (contain)
Quand un adherent n'a pas de photo de couverture mais un logo, le logo
n'est plus etire en plein cadre : il est centre et contenu (~80%) sur
fond blanc. Composant partage VitrineImage applique a l'annuaire, au
carrousel d'accueil et a la fiche adherent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 10:53:19 +02:00
MichaelandClaude Opus 4.8 c15213c131 Accueil: etoiles flottantes + animations forcees
- Retire le kill-switch prefers-reduced-motion (* { animation:none }) qui
  coupait toutes les animations : etoiles, flottement du logo, apparitions
  au defilement ne bougeaient pas. Animations desormais toujours actives.
- Nouveau StarField : champ d'etoiles qui scintillent ET derivent
  (keyframe plr-drift via propriete translate, cumulee au scintillement),
  place dans le hero. Contenu du hero passe au-dessus (z-index).
- Carrousel : fondu force (n'est plus desactive sous reduced-motion).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 10:46:11 +02:00
MichaelandClaude Opus 4.8 a4f03a21aa Accueil: carrousel 3 cartes avec rotation en fondu toutes les 20s
Remplace le defilement continu par 3 cartes fixes et propres. Toutes
les 20 s, les cartes disparaissent une a une (fondu decale) puis les
3 suivantes apparaissent une a une. Rotation equitable sur tous les
adherents actifs. Respecte prefers-reduced-motion (bascule sans fondu).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 10:36:51 +02:00
MichaelandClaude Opus 4.8 64ab10dea1 Accueil: logo centre, "A l'honneur" en carrousel auto
- Hero : logo centre verticalement (alignItems center)
- Titre "A l'honneur ce mois-ci" -> "A l'honneur"
- Remplace les 3 fiches "mise en avant" par un carrousel auto-defilant
  de tous les adherents actifs, en rotation equitable (l'ordre pivote
  d'un cran par heure). Pause au survol, respecte prefers-reduced-motion.
- Retire la coche "Mettre a l'honneur" du back-office (edition adherent)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 10:31:55 +02:00
MichaelandClaude Opus 4.8 b4d94f2115 Backend: edition image d'entete + logo des adherents
- Champs upload image d'entete (coverUrl) et logo (logoUrl) dans le
  formulaire d'edition d'un adherent (composant ImageField, fichier ->
  data-URL via hidden input)
- updateMember persiste desormais coverUrl + logoUrl, et revalide la
  fiche publique /adherents/[id]
- serverActions.bodySizeLimit a 4mb (les data-URL depassent la limite
  par defaut de 1mb)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 09:47:04 +02:00
MichaelandClaude Opus 4.8 141acffc1c Logo annuaire + modals devenir membre & contact
- Logo en haut a gauche de la page Annuaire (prop logo sur SiteHeader)
- Modal "Devenir adherent" sur les CTA accueil + annuaire : cree une
  demande d'adhesion (membership_requests) et alerte les admins via le
  journal d'activite (compteur tableau de bord deja cable)
- Formulaire de contact (modal depuis le pied de page) : nouvelle table
  contact_messages + alerte admin
- Composant Modal partage, server actions publiques (sans auth)
- Migration drizzle 0002

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 09:16:59 +02:00
Claude e2cf03c9f3 Anime la page d'accueil : apparitions au défilement + étoiles en mouvement
- Composant Reveal (IntersectionObserver) + keyframes CSS : sections et grilles
  apparaissent en fondu/glissement, cartes en cascade (stagger). Respecte
  prefers-reduced-motion + repli no-JS.
- Étoiles (sparkles) : l'animation twinkle inclut désormais une dérive
  (translation) pour un mouvement nettement visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwfhYHzC9hQWPDnQ2p53GL
2026-06-26 22:09:43 +00:00
Claude e5ce8ab528 Retire le logo + titre de l'en-tête (haut-gauche) et du pied de page (bas-gauche)
Le menu reste aligné à droite et le bloc contact à droite, conformément aux
maquettes d'origine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwfhYHzC9hQWPDnQ2p53GL
2026-06-26 21:43:45 +00:00
Claude 5b6445b571 En-tête/pied de page partagés et cohérents + retrait du bloc métiers
- Menu identique sur toutes les pages publiques (Accueil, Annuaire, Promotions,
  L'association, Espace adhérent) via SiteHeader/SiteFooter : on peut toujours
  revenir à l'accueil depuis l'annuaire et inversement (page courante en gras).
- Retire la section « Parcourir par métier » de la page d'accueil.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwfhYHzC9hQWPDnQ2p53GL
2026-06-26 21:34:30 +00:00
Claude 7e22ec50d4 Implémente le site Plein R (Accueil + Backend) sur Next.js + Postgres + Docker
Application unique Next.js (App Router, TypeScript) servant :
- Accueil public : héro, recherche, métiers, promotions, mises à l'honneur
  (données issues de Postgres)
- Backend authentifié avec RBAC : tableau de bord, adhérents (CRUD), modération
  des promotions, administrateurs, espace adhérent (publication avec aperçu)

Technique :
- Drizzle ORM + drizzle-kit (migrations versionnées) sur driver pg
- Auth.js v5 (credentials, sessions JWT), rôles admin/moderator/editor/member
- Middleware de protection de /backend + gardes par rôle dans chaque vue
- Server actions pour toutes les mutations (vérif auth + capacité + revalidate)
- Design fidèle aux maquettes (design-system CSS, animations, responsive)

Conteneurisation :
- 1 conteneur applicatif (sortie standalone) + 1 conteneur Postgres externe
- docker-compose avec healthcheck ; migrations + seed au démarrage
- scripts migrate/seed bundlés (esbuild) pour un runtime sans devDeps

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwfhYHzC9hQWPDnQ2p53GL
2026-06-26 12:06:21 +00:00