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
This commit is contained in:
Claude committed 2026-06-26 12:06:21 +00:00
commit 7e22ec50d4
45 files changed
+12013

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
import type { NextAuthConfig } from "next-auth";
/**
* Edge-safe Auth.js configuration (no database / bcrypt imports here).
* Shared between the middleware (edge runtime) and the full auth instance.
*/
export const authConfig = {
pages: {
signIn: "/login",
},
session: {
strategy: "jwt",
},
trustHost: true,
callbacks: {
jwt({ token, user }) {
if (user) {
token.uid = (user as { id?: string }).id ?? token.sub;
token.role = (user as { role?: string }).role;
token.memberId = (user as { memberId?: number | null }).memberId ?? null;
}
return token;
},
session({ session, token }) {
if (session.user) {
session.user.id = (token.uid as string) ?? "";
session.user.role = token.role as
| "admin"
| "moderator"
| "editor"
| "member";
session.user.memberId = (token.memberId as number | null) ?? null;
}
return session;
},
authorized({ auth, request }) {
const isLoggedIn = !!auth?.user;
const { pathname } = request.nextUrl;
if (pathname.startsWith("/backend")) {
return isLoggedIn;
}
return true;
},
},
providers: [],
} satisfies NextAuthConfig;