Skill for integrating Better Auth - the comprehensive TypeScript authentication framework.
Add this skill
npx mdskills install better-auth/best-practicesComprehensive reference guide with strong technical detail but lacks agent-specific trigger conditions
1---2name: better-auth-best-practices3description: Skill for integrating Better Auth - the comprehensive TypeScript authentication framework.4---56# Better Auth Integration Guide78**Always consult [better-auth.com/docs](https://better-auth.com/docs) for code examples and latest API.**910Better Auth is a TypeScript-first, framework-agnostic auth framework supporting email/password, OAuth, magic links, passkeys, and more via plugins.1112---1314## Quick Reference1516### Environment Variables17- `BETTER_AUTH_SECRET` - Encryption secret (min 32 chars). Generate: `openssl rand -base64 32`18- `BETTER_AUTH_URL` - Base URL (e.g., `https://example.com`)1920Only define `baseURL`/`secret` in config if env vars are NOT set.2122### File Location23CLI looks for `auth.ts` in: `./`, `./lib`, `./utils`, or under `./src`. Use `--config` for custom path.2425### CLI Commands26- `npx @better-auth/cli@latest migrate` - Apply schema (built-in adapter)27- `npx @better-auth/cli@latest generate` - Generate schema for Prisma/Drizzle28- `npx @better-auth/cli mcp --cursor` - Add MCP to AI tools2930**Re-run after adding/changing plugins.**3132---3334## Core Config Options3536| Option | Notes |37|--------|-------|38| `appName` | Optional display name |39| `baseURL` | Only if `BETTER_AUTH_URL` not set |40| `basePath` | Default `/api/auth`. Set `/` for root. |41| `secret` | Only if `BETTER_AUTH_SECRET` not set |42| `database` | Required for most features. See adapters docs. |43| `secondaryStorage` | Redis/KV for sessions & rate limits |44| `emailAndPassword` | `{ enabled: true }` to activate |45| `socialProviders` | `{ google: { clientId, clientSecret }, ... }` |46| `plugins` | Array of plugins |47| `trustedOrigins` | CSRF whitelist |4849---5051## Database5253**Direct connections:** Pass `pg.Pool`, `mysql2` pool, `better-sqlite3`, or `bun:sqlite` instance.5455**ORM adapters:** Import from `better-auth/adapters/drizzle`, `better-auth/adapters/prisma`, `better-auth/adapters/mongodb`.5657**Critical:** Better Auth uses adapter model names, NOT underlying table names. If Prisma model is `User` mapping to table `users`, use `modelName: "user"` (Prisma reference), not `"users"`.5859---6061## Session Management6263**Storage priority:**641. If `secondaryStorage` defined → sessions go there (not DB)652. Set `session.storeSessionInDatabase: true` to also persist to DB663. No database + `cookieCache` → fully stateless mode6768**Cookie cache strategies:**69- `compact` (default) - Base64url + HMAC. Smallest.70- `jwt` - Standard JWT. Readable but signed.71- `jwe` - Encrypted. Maximum security.7273**Key options:** `session.expiresIn` (default 7 days), `session.updateAge` (refresh interval), `session.cookieCache.maxAge`, `session.cookieCache.version` (change to invalidate all sessions).7475---7677## User & Account Config7879**User:** `user.modelName`, `user.fields` (column mapping), `user.additionalFields`, `user.changeEmail.enabled` (disabled by default), `user.deleteUser.enabled` (disabled by default).8081**Account:** `account.modelName`, `account.accountLinking.enabled`, `account.storeAccountCookie` (for stateless OAuth).8283**Required for registration:** `email` and `name` fields.8485---8687## Email Flows8889- `emailVerification.sendVerificationEmail` - Must be defined for verification to work90- `emailVerification.sendOnSignUp` / `sendOnSignIn` - Auto-send triggers91- `emailAndPassword.sendResetPassword` - Password reset email handler9293---9495## Security9697**In `advanced`:**98- `useSecureCookies` - Force HTTPS cookies99- `disableCSRFCheck` - ⚠️ Security risk100- `disableOriginCheck` - ⚠️ Security risk101- `crossSubDomainCookies.enabled` - Share cookies across subdomains102- `ipAddress.ipAddressHeaders` - Custom IP headers for proxies103- `database.generateId` - Custom ID generation or `"serial"`/`"uuid"`/`false`104105**Rate limiting:** `rateLimit.enabled`, `rateLimit.window`, `rateLimit.max`, `rateLimit.storage` ("memory" | "database" | "secondary-storage").106107---108109## Hooks110111**Endpoint hooks:** `hooks.before` / `hooks.after` - Array of `{ matcher, handler }`. Use `createAuthMiddleware`. Access `ctx.path`, `ctx.context.returned` (after), `ctx.context.session`.112113**Database hooks:** `databaseHooks.user.create.before/after`, same for `session`, `account`. Useful for adding default values or post-creation actions.114115**Hook context (`ctx.context`):** `session`, `secret`, `authCookies`, `password.hash()`/`verify()`, `adapter`, `internalAdapter`, `generateId()`, `tables`, `baseURL`.116117---118119## Plugins120121**Import from dedicated paths for tree-shaking:**122```123import { twoFactor } from "better-auth/plugins/two-factor"124```125NOT `from "better-auth/plugins"`.126127**Popular plugins:** `twoFactor`, `organization`, `passkey`, `magicLink`, `emailOtp`, `username`, `phoneNumber`, `admin`, `apiKey`, `bearer`, `jwt`, `multiSession`, `sso`, `oauthProvider`, `oidcProvider`, `openAPI`, `genericOAuth`.128129Client plugins go in `createAuthClient({ plugins: [...] })`.130131---132133## Client134135Import from: `better-auth/client` (vanilla), `better-auth/react`, `better-auth/vue`, `better-auth/svelte`, `better-auth/solid`.136137Key methods: `signUp.email()`, `signIn.email()`, `signIn.social()`, `signOut()`, `useSession()`, `getSession()`, `revokeSession()`, `revokeSessions()`.138139---140141## Type Safety142143Infer types: `typeof auth.$Infer.Session`, `typeof auth.$Infer.Session.user`.144145For separate client/server projects: `createAuthClient<typeof auth>()`.146147---148149## Common Gotchas1501511. **Model vs table name** - Config uses ORM model name, not DB table name1522. **Plugin schema** - Re-run CLI after adding plugins1533. **Secondary storage** - Sessions go there by default, not DB1544. **Cookie cache** - Custom session fields NOT cached, always re-fetched1555. **Stateless mode** - No DB = session in cookie only, logout on cache expiry1566. **Change email flow** - Sends to current email first, then new email157158---159160## Resources161162- [Docs](https://better-auth.com/docs)163- [Options Reference](https://better-auth.com/docs/reference/options)164- [LLMs.txt](https://better-auth.com/llms.txt)165- [GitHub](https://github.com/better-auth/better-auth)166- [Init Options Source](https://github.com/better-auth/better-auth/blob/main/packages/core/src/types/init-options.ts)
Full transparency — inspect the skill content before installing.