Prompt-to-PR: Agregar Better Auth a una App de Next.js
SOP completo para integrar Better Auth en un proyecto Next.js App Router — sesiones, correo/contraseña, OAuth y protección de middleware en un solo paso.
CursorClaude CodeCodexWindsurf Next.jsTypeScriptPostgreSQL
Un manual completo para agregar Better Auth a un proyecto existente de Next.js 15 App Router respaldado por PostgreSQL. Abarca el servidor de autenticación, el manejador de rutas, el ayudante del cliente, el middleware y la interfaz de inicio de sesión en una sola ejecución del agente.
1. Requisito
Agregar autenticación basada en sesiones con correo/contraseña y OAuth de GitHub. Proteger todas las rutas bajo /dashboard mediante el middleware de Next.js. Almacenar sesiones en la base de datos PostgreSQL existente usando el adaptador Drizzle integrado de Better Auth.
2. Primer 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. Cambios esperados en archivos
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. Lista de verificación
BETTER_AUTH_SECRETtiene al menos 32 bytes aleatorios — nunca codificado.- El manejador de ruta comodín exporta tanto
GETcomoPOST. src/middleware.tsusamatcherpara omitir_next/static,_next/imagey/api/auth.- El adaptador Drizzle recibe la misma instancia de
dbutilizada en otros lugares — sin segunda conexión. createAuthClient()enauth-client.tsapunta albaseURLcorrecto (leeNEXT_PUBLIC_APP_URL).- La página de inicio de sesión es un Componente Cliente (
"use client") — sin importaciones solo de servidor. - La URL de devolución de llamada de OAuth de GitHub en la configuración de la app de GitHub coincide con
/api/auth/callback/github. - Se agregan nuevas tablas de esquema, no se reemplazan las existentes.
5. Comandos de prueba
# Generate and run the new auth migrationsnpx drizzle-kit generatenpx drizzle-kit migrate
# Start dev serverbun dev
# Smoke-test: attempt to hit protected route without a sessioncurl -I http://localhost:3000/dashboard# Expect: 307 redirect to /sign-in
# Run any existing test suitebun test6. Fallos comunes
BETTER_AUTH_SECRETfaltante en tiempo de ejecución — Better Auth arroja un error al inicio. Agrégalo a.env.local; confirma conconsole.log(process.env.BETTER_AUTH_SECRET?.length)enauth.ts(elimina después).- Conexión Drizzle duplicada — el agente crea una segunda llamada
drizzle()dentro deauth.tsen lugar de importar desdesrc/db/index.ts. Causa dos grupos de conexiones. - Middleware coincide con
/api/auth— causa un bucle infinito de redirección. Elmatcherdebe excluir/api/auth/(.*). - Componente cliente importa
authsolo de servidor — error de compilación. Soloauth-client.tsdebe importarse en Componentes Cliente. - Discrepancia en la URL de devolución de GitHub — OAuth falla silenciosamente. Confirma que la devolución de la app OAuth de GitHub es
http://localhost:3000/api/auth/callback/githuben desarrollo.
7. Prompt de corrección
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 thancreating a second Drizzle instance.8. Descripción del PR
## 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`