P PasteCode
Playbook

Prompt-to-PR : Ajouter Better Auth à une application Next.js

SOP complet pour intégrer Better Auth dans un projet Next.js App Router — sessions, email/mot de passe, OAuth et protection middleware en une seule passe.

CursorClaude CodeCodexWindsurf Next.jsTypeScriptPostgreSQL
.md .json Difficulté: Moyen Mis à jour 8 juin 2026

Un guide complet pour ajouter Better Auth à un projet Next.js 15 App Router existant utilisant PostgreSQL. Couvre le serveur d’authentification, le gestionnaire de routes, l’aide client, le middleware et l’interface de connexion en une seule exécution d’agent.

1. Exigence

Ajoutez une authentification basée sur les sessions avec email/mot de passe et OAuth GitHub. Protégez toutes les routes sous /dashboard via le middleware Next.js. Stockez les sessions dans la base de données PostgreSQL existante en utilisant l’adaptateur Drizzle intégré de Better Auth.

2. Première invite

First Prompt
Add Better Auth to this Next.js 15 App Router project.
Stack: PostgreSQL (Drizzle ORM, schema in src/db/schema.ts), TypeScript, Tailwind.
Tasks:
1. Install `better-auth` and `@better-auth/drizzle`.
2. Create `src/lib/auth.ts` — configure BetterAuth with the Drizzle adapter,
emailAndPassword plugin, and GitHub socialProvider. Read secrets from
BETTER_AUTH_SECRET, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET env vars.
3. Create `src/app/api/auth/[...all]/route.ts` that re-exports the auth handler
for GET and POST.
4. Create `src/lib/auth-client.ts` that exports a `createAuthClient()` instance
for client components.
5. Add Better Auth tables to `src/db/schema.ts` using `auth.api.generateSchema()`.
6. Create `src/middleware.ts` that protects every route under `/dashboard`;
redirect unauthenticated requests to `/sign-in`.
7. Create `src/app/(auth)/sign-in/page.tsx` — a minimal email/password form and
a "Continue with GitHub" button using the auth client.
8. Do not touch any existing route or component unless strictly necessary.

3. Modifications de fichiers attendues

package.json (better-auth, @better-auth/drizzle)
src/lib/auth.ts (new — server auth instance)
src/lib/auth-client.ts (new — browser auth client)
src/app/api/auth/[...all]/route.ts (new — catch-all route handler)
src/db/schema.ts (new tables: user, session, account, verification)
src/middleware.ts (new — route protection)
src/app/(auth)/sign-in/page.tsx (new — sign-in UI)
.env.local.example (BETTER_AUTH_SECRET, GITHUB_* vars)

4. Liste de vérification

  • BETTER_AUTH_SECRET fait au moins 32 octets aléatoires — jamais codé en dur.
  • Le gestionnaire de route universel exporte à la fois GET et POST.
  • src/middleware.ts utilise matcher pour ignorer _next/static, _next/image et /api/auth.
  • L’adaptateur Drizzle reçoit la même instance db utilisée ailleurs — pas de seconde connexion.
  • createAuthClient() dans auth-client.ts pointe vers le bon baseURL (lit NEXT_PUBLIC_APP_URL).
  • La page de connexion est un composant client ("use client") — pas d’imports réservés au serveur.
  • L’URL de rappel OAuth GitHub dans les paramètres de l’application GitHub correspond à /api/auth/callback/github.
  • Les nouvelles tables de schéma sont ajoutées, ne remplaçant pas les tables existantes.

5. Commandes de test

Terminal window
# Generate and run the new auth migrations
npx drizzle-kit generate
npx drizzle-kit migrate
# Start dev server
bun dev
# Smoke-test: attempt to hit protected route without a session
curl -I http://localhost:3000/dashboard
# Expect: 307 redirect to /sign-in
# Run any existing test suite
bun test

6. Échecs courants

  • BETTER_AUTH_SECRET manquant à l’exécution — Better Auth lève une erreur au démarrage. Ajoutez-le dans .env.local ; confirmez avec console.log(process.env.BETTER_AUTH_SECRET?.length) dans auth.ts (supprimez ensuite).
  • Double connexion Drizzle — l’agent crée un second appel drizzle() dans auth.ts au lieu d’importer depuis src/db/index.ts. Provoque deux pools de connexions.
  • Le middleware correspond à /api/auth — provoque une boucle de redirection infinie. Le matcher doit exclure /api/auth/(.*).
  • Le composant client importe auth réservé au serveur — erreur de build. Seul auth-client.ts doit être importé dans les composants clients.
  • Non-correspondance de l’URL de rappel GitHub — OAuth échoue silencieusement. Confirmez que le rappel de l’application OAuth GitHub est http://localhost:3000/api/auth/callback/github en développement.

7. Invite de correction

Fix Prompt
The middleware is redirecting /api/auth/* to /sign-in, causing an infinite loop.
Fix src/middleware.ts so the matcher explicitly excludes:
- /api/auth/:path*
- /_next/static/:path*
- /_next/image
- /favicon.ico
Also confirm that auth.ts imports `db` from `src/db/index.ts` rather than
creating a second Drizzle instance.

8. Description de la PR

PR description
## Auth: Add Better Auth (email/password + GitHub OAuth)
- Installs `better-auth` with Drizzle adapter against the existing PostgreSQL db
- Catch-all `/api/auth/[...all]` route handles all auth requests
- Middleware protects `/dashboard/**`; unauthenticated → `/sign-in`
- New sign-in page with email/password form and GitHub OAuth button
- Four new schema tables (`user`, `session`, `account`, `verification`) via migration
**Env vars required** (see `.env.local.example`):
- `BETTER_AUTH_SECRET` — min 32-byte random string
- `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`
- `NEXT_PUBLIC_APP_URL`