skills/better-auth/better-auth-best-practices/SKILL.md
Configure Better Auth server and client, set up database adapters, manage sessions, add plugins, and handle environment variables. Use when users mention Better Auth, betterauth, auth.ts, or need to set up TypeScript authentication with email/password, OAuth, or plugin configuration.
npx skillsauth add aiskillstore/marketplace better-auth-best-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Always consult better-auth.com/docs for code examples and latest API.
npm install better-authBETTER_AUTH_SECRET and BETTER_AUTH_URLauth.ts with database + confignpx @better-auth/cli@latest migrateGET /api/auth/ok — should return { status: "ok" }BETTER_AUTH_SECRET - Encryption secret (min 32 chars). Generate: openssl rand -base64 32BETTER_AUTH_URL - Base URL (e.g., https://example.com)Only define baseURL/secret in config if env vars are NOT set.
CLI looks for auth.ts in: ./, ./lib, ./utils, or under ./src. Use --config for custom path.
npx @better-auth/cli@latest migrate - Apply schema (built-in adapter)npx @better-auth/cli@latest generate - Generate schema for Prisma/Drizzlenpx @better-auth/cli mcp --cursor - Add MCP to AI toolsRe-run after adding/changing plugins.
| Option | Notes |
|--------|-------|
| appName | Optional display name |
| baseURL | Only if BETTER_AUTH_URL not set |
| basePath | Default /api/auth. Set / for root. |
| secret | Only if BETTER_AUTH_SECRET not set |
| database | Required for most features. See adapters docs. |
| secondaryStorage | Redis/KV for sessions & rate limits |
| emailAndPassword | { enabled: true } to activate |
| socialProviders | { google: { clientId, clientSecret }, ... } |
| plugins | Array of plugins |
| trustedOrigins | CSRF whitelist |
Direct connections: Pass pg.Pool, mysql2 pool, better-sqlite3, or bun:sqlite instance.
ORM adapters: Import from better-auth/adapters/drizzle, better-auth/adapters/prisma, better-auth/adapters/mongodb.
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".
Storage priority:
secondaryStorage defined → sessions go there (not DB)session.storeSessionInDatabase: true to also persist to DBcookieCache → fully stateless modeCookie cache strategies:
compact (default) - Base64url + HMAC. Smallest.jwt - Standard JWT. Readable but signed.jwe - Encrypted. Maximum security.Key options: session.expiresIn (default 7 days), session.updateAge (refresh interval), session.cookieCache.maxAge, session.cookieCache.version (change to invalidate all sessions).
User: user.modelName, user.fields (column mapping), user.additionalFields, user.changeEmail.enabled (disabled by default), user.deleteUser.enabled (disabled by default).
Account: account.modelName, account.accountLinking.enabled, account.storeAccountCookie (for stateless OAuth).
Required for registration: email and name fields.
emailVerification.sendVerificationEmail - Must be defined for verification to workemailVerification.sendOnSignUp / sendOnSignIn - Auto-send triggersemailAndPassword.sendResetPassword - Password reset email handlerIn advanced:
useSecureCookies - Force HTTPS cookiesdisableCSRFCheck - ⚠️ Security riskdisableOriginCheck - ⚠️ Security riskcrossSubDomainCookies.enabled - Share cookies across subdomainsipAddress.ipAddressHeaders - Custom IP headers for proxiesdatabase.generateId - Custom ID generation or "serial"/"uuid"/falseRate limiting: rateLimit.enabled, rateLimit.window, rateLimit.max, rateLimit.storage ("memory" | "database" | "secondary-storage").
Endpoint hooks: hooks.before / hooks.after - Array of { matcher, handler }. Use createAuthMiddleware. Access ctx.path, ctx.context.returned (after), ctx.context.session.
Database hooks: databaseHooks.user.create.before/after, same for session, account. Useful for adding default values or post-creation actions.
Hook context (ctx.context): session, secret, authCookies, password.hash()/verify(), adapter, internalAdapter, generateId(), tables, baseURL.
Import from dedicated paths for tree-shaking:
import { twoFactor } from "better-auth/plugins/two-factor"
NOT from "better-auth/plugins".
Popular plugins: twoFactor, organization, passkey, magicLink, emailOtp, username, phoneNumber, admin, apiKey, bearer, jwt, multiSession, sso, oauthProvider, oidcProvider, openAPI, genericOAuth.
Client plugins go in createAuthClient({ plugins: [...] }).
Import from: better-auth/client (vanilla), better-auth/react, better-auth/vue, better-auth/svelte, better-auth/solid.
Key methods: signUp.email(), signIn.email(), signIn.social(), signOut(), useSession(), getSession(), revokeSession(), revokeSessions().
Infer types: typeof auth.$Infer.Session, typeof auth.$Infer.Session.user.
For separate client/server projects: createAuthClient<typeof auth>().
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.