Better Auth Best Practices
Implementation and migration guide for Better Auth, the framework-agnostic TypeScript authentication and authorization library. This skill contains 42 rules organized by impact across 8 categories, derived from the official documentation and migration guides.
When to Apply
Reference these guidelines when:
- Setting up a fresh Better Auth instance (config, adapter, route handler, client)
- Wiring framework-specific integrations (Next.js App/Pages Router, SvelteKit, Hono, Express, Nuxt, Astro)
- Configuring sessions, cookies, and security (rate limit, trusted origins, password hashing)
- Adding plugins: 2FA, organization, admin, magicLink, JWT, passkey, multi-session
- Migrating from another auth library (NextAuth/Auth.js, Clerk, Auth0, Supabase Auth)
- Debugging "session is null" / "redirect_uri_mismatch" / 403 CSRF errors
- Reviewing PRs that touch
lib/auth.ts,auth-client.ts, or/api/auth/route handlers
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Setup & Configuration | CRITICAL | setup- |
| 2 | Database Adapters & Schema | CRITICAL | db- |
| 3 | API Route Handlers | CRITICAL | route- |
| 4 | Session & Cookies | HIGH | session- |
| 5 | Auth Methods & Providers | HIGH | auth- |
| 6 | Security & Hardening | HIGH | security- |
| 7 | Plugins & Extensions | MEDIUM | plugins- |
| 8 | Migration from Other Auth | MEDIUM | migrate- |
Quick Reference
1. Setup & Configuration (CRITICAL)
setup-secret— Set a strongBETTER_AUTH_SECRETper environmentsetup-base-url— Configure an explicitbaseURLper environmentsetup-client-base-url— Match the clientbaseURLto the serversetup-singleton— Export a single auth instance from a server-only modulesetup-trusted-origins— ConfiguretrustedOriginsfor all non-baseURL callers
2. Database Adapters & Schema (CRITICAL)
db-adapter-selection— Pick the adapter that matches your ORMdb-schema-generate— Runauth generatethen ORM migrate before every deploydb-additional-fields— Extend the user schema viaadditionalFieldsdb-plugin-schema-customization— Rename plugin tables via theschemaoptiondb-database-hooks— UsedatabaseHooksfor cross-cutting logicdb-connection-pooling— Share one pooled DB client with the rest of your app
3. API Route Handlers (CRITICAL)
route-mount-catchall— Mount the catch-all handler at/api/auth/[...all]route-runtime-selection— Use the Node.js runtime for middleware that callsauth.apiroute-no-body-consumers— Mount auth before any body-parsing middleware
4. Session & Cookies (HIGH)
session-server-vs-client— Useauth.api.getSessionon server,authClient.useSessionon clientsession-expiry-tuning— ConfigureexpiresInandupdateAgetogethersession-cookie-cache— EnablecookieCacheto cut session DB lookupssession-cookie-attributes— SetsameSite,secure,partitionedfor cross-site flowssession-cross-subdomain— EnablecrossSubDomainCookiesfor multi-subdomain appssession-customsession-fields— UsecustomSessionto add computed fields
5. Auth Methods & Providers (HIGH)
auth-require-email-verification— EnablerequireEmailVerificationwithsendVerificationEmailauth-oauth-redirect-uri— Match OAuthredirectURIexactly with the provider consoleauth-oauth-env-vars— Load OAuth credentials from environment, never inlineauth-magic-link-setup— ImplementsendMagicLinkbefore enabling themagicLinkpluginauth-client-sign-in-helpers— UseauthClient.signIn.socialwithcallbackURLauth-infer-additional-fields— AddinferAdditionalFieldsto the client for type sync
6. Security & Hardening (HIGH)
security-rate-limit— EnablerateLimitwith persistent storage in productionsecurity-password-hash-interop— Override hash function when migrating from bcrypt/argon2security-revoke-on-password-reset— EnablerevokeSessionsOnPasswordResetsecurity-min-password-length— SetminPasswordLengthto at least 10security-trusted-origins-strict— Never wildcardtrustedOrigins
7. Plugins & Extensions (MEDIUM)
plugins-next-cookies-last— PlacenextCookies()as the LAST plugin in Next.jsplugins-two-factor-issuer— SetappNameas the 2FA issuerplugins-shared-access-control— Defineac+ roles once, share server/clientplugins-pair-client-server— Pair every server plugin with its client counterpartplugins-organization-active-context— Set active organization on sessionplugins-jwt-when-to-use— Use thejwtplugin only for external service consumersplugins-admin-impersonation— Use admin plugin'simpersonatemethod for support access
8. Migration from Other Auth (MEDIUM)
migrate-parallel-cutover— Run Better Auth alongside legacy auth during cutovermigrate-oauth-account-mapping— Map legacy OAuth identities toaccountrowsmigrate-force-allow-id— UseforceAllowIdto preserve existing user IDsmigrate-nextauth-schema-mapping— Map NextAuth v5 columns field-by-field
How to Use
For a fresh implementation, read in priority order: start with all setup- rules, then db-, then route- — these CRITICAL categories must be correct or nothing else works. After the foundation, pick the rules that match your scope: session- for cookie/expiry tuning, auth- for provider configuration, security- for production hardening.
For a migration from another auth library, read migrate-parallel-cutover first (strategy), then security-password-hash-interop (preserve user passwords), then migrate-oauth-account-mapping and migrate-nextauth-schema-mapping (data layout).
Read individual reference files for detailed explanations, incorrect vs. correct code examples, and links to the canonical Better Auth documentation.
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Category definitions ordered by impact |
| assets/templates/_template.md | Template for adding new rules |
| metadata.json | Version, references, and discipline metadata |