P PasteCode
Playbook

Prompt-to-PR: Adicionar Better Auth a um App Next.js

SOP completo para integrar Better Auth a um projeto Next.js App Router — sessões, email/senha, OAuth e proteção de middleware em uma única execução.

CursorClaude CodeCodexWindsurf Next.jsTypeScriptPostgreSQL
.md .json Dificuldade: Médio Atualizado 8 de jun. de 2026

Um playbook completo para adicionar Better Auth a um projeto Next.js 15 App Router existente com PostgreSQL. Abrange o servidor de autenticação, manipulador de rotas, helper do cliente, middleware e UI de login em uma única execução do agente.

1. Requisito

Adicionar autenticação baseada em sessão com email/senha e GitHub OAuth. Proteger todas as rotas em /dashboard via middleware do Next.js. Armazenar sessões no banco de dados PostgreSQL existente usando o adaptador Drizzle integrado do Better Auth.

2. Primeiro Prompt

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. Alterações de Arquivos Esperadas

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 Verificação de Revisão

  • BETTER_AUTH_SECRET tem pelo menos 32 bytes aleatórios — nunca codificado.
  • O manipulador de rota catch-all exporta tanto GET quanto POST.
  • src/middleware.ts usa matcher para pular _next/static, _next/image e /api/auth.
  • O adaptador Drizzle recebe a mesma instância db usada em outros lugares — sem segunda conexão.
  • createAuthClient() em auth-client.ts aponta para o baseURL correto (lê NEXT_PUBLIC_APP_URL).
  • A página de login é um Client Component ("use client") — sem imports exclusivos do servidor.
  • A URL de callback do GitHub OAuth nas configurações do app GitHub corresponde a /api/auth/callback/github.
  • Novas tabelas de esquema são adicionadas, não substituindo, as tabelas existentes.

5. Comandos de Teste

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. Falhas Comuns

  • BETTER_AUTH_SECRET ausente em tempo de execução — Better Auth lança erro na inicialização. Adicione ao .env.local; confirme com console.log(process.env.BETTER_AUTH_SECRET?.length) em auth.ts (remova depois).
  • Conexão Drizzle duplicada — o agente cria uma segunda chamada drizzle() dentro de auth.ts em vez de importar de src/db/index.ts. Causa dois pools de conexão.
  • Middleware corresponde a /api/auth — causa loop infinito de redirecionamento. O matcher deve excluir /api/auth/(.*).
  • Client Component importa auth exclusivo do servidor — erro de build. Apenas auth-client.ts deve ser importado em Client Components.
  • URL de callback do GitHub incorreta — OAuth falha silenciosamente. Confirme que o callback do app GitHub OAuth é http://localhost:3000/api/auth/callback/github em desenvolvimento.

7. Prompt de Correção

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. Descrição do 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`