Claude-skills better-auth
Skill for integrating Better Auth - comprehensive TypeScript authentication framework for Cloudflare D1, Next.js, Nuxt, and 15+ frameworks. Use when adding auth, encountering D1 adapter errors, or implementing OAuth/2FA/RBAC features.
git clone https://github.com/secondsky/claude-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/secondsky/claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/better-auth/skills/better-auth" ~/.claude/skills/secondsky-claude-skills-better-auth && rm -rf "$T"
plugins/better-auth/skills/better-auth/SKILL.mdbetter-auth
Status: Production Ready Last Updated: 2026-04-08 Package:
better-auth@1.6.0 (ESM-only)
Dependencies: Drizzle ORM or Kysely (required for D1 complex use cases; D1 native support available in v1.5+)
Quick Start (5 Minutes)
Installation
Option 1: Drizzle ORM (Recommended)
bun add better-auth drizzle-orm drizzle-kit
Option 2: Kysely
bun add better-auth kysely @noxharmonium/kysely-d1
⚠️ v1.4.0+ Requirements
better-auth v1.4.0+ is ESM-only. Ensure:
package.json:
{ "type": "module" }
Upgrading from v1.3.x? Load
references/migration-guide-1.4.0.md
Upgrading from v1.4.x? Load references/migration-guide-1.5.0.md
⚠️ CRITICAL: D1 Adapter Requirements
v1.5.0+: D1 is now natively supported. Pass your D1 binding directly:
// ✅ SIMPLEST - D1 native (v1.5.0+) import { betterAuth } from "better-auth"; const auth = betterAuth({ database: env.DB, // D1 binding, auto-detected });
For complex schemas, use Drizzle ORM:
// ✅ RECOMMENDED for complex schemas - Drizzle import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { drizzle } from "drizzle-orm/d1"; const auth = betterAuth({ database: drizzleAdapter(drizzle(env.DB, { schema }), { provider: "sqlite" }), });
// ❌ WRONG - This doesn't exist import { d1Adapter } from 'better-auth/adapters/d1'
Minimal Setup (Cloudflare Workers + Drizzle)
1. Create D1 Database:
wrangler d1 create my-app-db
2. Define Schema (
src/db/schema.ts):
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; export const user = sqliteTable("user", { id: text().primaryKey(), name: text().notNull(), email: text().notNull().unique(), emailVerified: integer({ mode: "boolean" }).notNull().default(false), image: text(), }); export const session = sqliteTable("session", { id: text().primaryKey(), userId: text().notNull().references(() => user.id, { onDelete: "cascade" }), token: text().notNull(), expiresAt: integer({ mode: "timestamp" }).notNull(), }); // See references/database-schema.ts for complete schema
3. Initialize Auth (
src/auth.ts):
import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { drizzle } from "drizzle-orm/d1"; import * as schema from "./db/schema"; export function createAuth(env: { DB: D1Database; BETTER_AUTH_SECRET: string }) { const db = drizzle(env.DB, { schema }); return betterAuth({ baseURL: env.BETTER_AUTH_URL, secret: env.BETTER_AUTH_SECRET, database: drizzleAdapter(db, { provider: "sqlite" }), emailAndPassword: { enabled: true }, }); }
4. Create Worker (
src/index.ts):
import { Hono } from "hono"; import { createAuth } from "./auth"; const app = new Hono<{ Bindings: Env }>(); app.all("/api/auth/*", async (c) => { const auth = createAuth(c.env); return auth.handler(c.req.raw); }); export default app;
5. Deploy:
bunx drizzle-kit generate wrangler d1 migrations apply my-app-db --remote wrangler deploy
Decision Tree
For code examples and syntax, always consult better-auth.com/docs.
Is this a new/empty project? ├─ YES → New project setup │ 1. Identify framework (Next.js, Nuxt, Workers, etc.) │ 2. Choose database (D1, PostgreSQL, MongoDB, MySQL) │ 3. Install better-auth + Drizzle/Kysely │ 4. Create auth.ts + auth-client.ts │ 5. Set up route handler (see Quick Start above) │ 6. Run migrations (Drizzle Kit for D1) │ 7. Add features via plugins (2FA, organizations, etc.) │ └─ NO → Does project have existing auth? ├─ YES → Migration/enhancement │ • Audit current auth for gaps │ • Plan incremental migration │ • See references/framework-comparison.md for migration guides │ └─ NO → Add auth to existing project 1. Analyze project structure 2. Install better-auth + adapter 3. Create auth config (see Quick Start) 4. Add route handler to existing routes 5. Run schema migrations 6. Integrate into existing pages/components
Critical Rules
MUST DO
✅ Use
better-auth/minimal + adapter packages for smallest bundle (v1.5+)
✅ Use npx auth migrate and npx auth generate for CLI commands (v1.5+)
✅ Set BETTER_AUTH_SECRET via wrangler secret put
✅ Configure CORS with credentials: true
✅ Match OAuth callback URLs exactly (no trailing slash)
✅ Apply migrations to local D1 before wrangler dev
✅ Use camelCase column names in schema
NEVER DO
❌ Use
d1Adapter (doesn't exist)
❌ Forget CORS credentials or mismatch OAuth URLs
❌ Use snake_case columns without CamelCasePlugin
❌ Skip local migrations or hardcode secrets
❌ Leave sendVerificationEmail unimplemented
⚠️ v1.5.0 Breaking Changes
API Key Plugin Moved:
- import { apiKey } from "better-auth/plugins"; + import { apiKey } from "@better-auth/api-key";
Schema:
userId → referenceId, new configId field.
After Hooks: Database after-hooks now run post-transaction (not inside it).
Deprecated APIs Removed:
Adapter → DBAdapter, InferUser/InferSession removed, @better-auth/core/utils split into subpath exports.
Load
when upgrading from <1.5.0references/migration-guide-1.5.0.md
⚠️ v1.6.0 Breaking Changes
Session Freshness:
freshAge now uses createdAt (not updatedAt). Sessions may require re-auth more frequently for sensitive operations.
SAML Security: InResponseTo validation is default ON. Opt out with
saml: { enableInResponseToValidation: false }.
OIDC Provider Deprecated: Use
@better-auth/oauth-provider instead.
New in v1.5.0 (Highlights)
- New CLI:
npx auth init/migrate/generate/upgrade - D1 Native: Pass D1 binding directly (no adapter needed)
- OAuth 2.1 Provider:
(MCP-ready)@better-auth/oauth-provider - Electron:
for desktop apps@better-auth/electron - i18n:
for error translations@better-auth/i18n - Dynamic Base URL: Multi-domain/preview deployment support
- Secret Key Rotation: Non-destructive, versioned secrets
- Test Utils: Factories, OTP capture, login helpers
- Typed Error Codes: Machine-readable
in error responsescode
Load
for detailed implementation guides.references/v1.5-features.md
New in v1.6.0 (Highlights)
- OpenTelemetry: Distributed tracing (experimental)
- Passkey Pre-Auth: Register passkeys before session
- Non-blocking Scrypt: Password hashing on libuv thread pool
- 46% Smaller Package: 4.2MB → 2.3MB
- Case Insensitive Queries:
on adapter queriesmode: "insensitive"
Load
for detailed implementation guides.references/v1.6-features.md
Quick Reference
Environment Variables
| Variable | Purpose | Example |
|---|---|---|
| Encryption secret (min 32 chars) | Generate: |
| Base URL | or |
| Database connection (optional for D1) | PostgreSQL/MySQL connection string |
Note: Only define
baseURL/secret in config if env vars are NOT set.
CLI Commands (v1.5+)
| Command | Purpose |
|---|---|
| Interactive project scaffolding |
| Run database migrations |
| Generate auth schema |
| Adapter-specific schema |
| Upgrade to latest version |
| D1: Use this to generate Drizzle migrations |
| D1: Use this to apply migrations |
Re-run after adding/changing plugins.
Core Config Options
| Option | Notes |
|---|---|
| Optional display name |
| Only if not set |
| Default . Set for root. |
| Only if not set (min 32 chars) |
| Required for most features. Use or Kysely for D1 |
| Redis/KV for sessions & rate limits |
| to activate |
| |
| Array of plugins (import from dedicated paths) |
| CSRF whitelist for cross-origin requests |
Common Plugins
Import from dedicated packages (extracted in v1.5+):
import { twoFactor } from "better-auth/plugins/two-factor" import { organization } from "better-auth/plugins/organization" import { passkey } from "@better-auth/passkey" // Separate package import { apiKey } from "@better-auth/api-key" // Separate package (v1.5+) import { sso } from "@better-auth/sso" // Separate package (v1.5+) import { i18n } from "@better-auth/i18n" // Separate package (v1.5+) import { oauthProvider } from "@better-auth/oauth-provider" // Separate package (v1.5+)
Core plugins (still in
better-auth/plugins): twoFactor, organization, admin, anonymous, emailOTP, magicLink, phone-number, multi-session, custom-session.
Top 5 Errors (See references/error-catalog.md for all 15)
Error #1: "d1Adapter is not exported"
Problem: Trying to use non-existent
d1Adapter
Solution: Use drizzleAdapter or Kysely instead (see Quick Start above)
Error #2: Schema Generation Fails
Problem:
better-auth migrate doesn't work with D1
Solution: Use bunx drizzle-kit generate then wrangler d1 migrations apply
Error #3: CamelCase vs snake_case Mismatch
Problem: Database uses
email_verified but better-auth expects emailVerified
Solution: Use camelCase in schema or add CamelCasePlugin to Kysely
Error #4: CORS Errors
Problem:
Access-Control-Allow-Origin errors, cookies not sent
Solution: Configure CORS with credentials: true and correct origins
Error #5: OAuth Redirect URI Mismatch
Problem: Social sign-in fails with "redirect_uri_mismatch" Solution: Ensure exact match:
https://yourdomain.com/api/auth/callback/google
Load
for all 15 errors with detailed solutions.references/error-catalog.md
Common Use Cases
Use Case 1: Email/Password Authentication
When: Basic authentication without social providers Quick Pattern:
// Client await authClient.signIn.email({ email: "user@example.com", password: "password123", }); // Server - enable in config emailAndPassword: { enabled: true, requireEmailVerification: true, }
Load:
references/setup-guide.md → Step 5
Use Case 2: Social Authentication (45+ Providers)
When: Allow users to sign in with social accounts Supported: Google, GitHub, Microsoft, Apple, Discord, TikTok, Twitch, Spotify, LinkedIn, Slack, Reddit, Facebook, Twitter/X, Patreon, Vercel, Kick, and 30+ more. Quick Pattern:
// Client await authClient.signIn.social({ provider: "google", callbackURL: "/dashboard", }); // Server config socialProviders: { google: { clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, scope: ["openid", "email", "profile"], }, }
Load:
references/setup-guide.md → Step 5
Use Case 3: Protected API Routes
When: Need to verify user is authenticated Quick Pattern:
app.get("/api/protected", async (c) => { const auth = createAuth(c.env); const session = await auth.api.getSession({ headers: c.req.raw.headers, }); if (!session) { return c.json({ error: "Unauthorized" }, 401); } return c.json({ data: "protected", user: session.user }); });
Load:
references/cloudflare-worker-drizzle.ts
Use Case 4: Multi-Tenant with Organizations
When: Building SaaS with teams/organizations Load:
references/advanced-features.md → Organizations & Teams
Use Case 5: Two-Factor Authentication
When: Need extra security with 2FA/TOTP Load:
references/advanced-features.md → Two-Factor Authentication
When to Load References
Load
when:references/setup-guide.md
- User needs complete 8-step setup walkthrough
- User asks about Kysely adapter alternative
- User needs help with migrations or deployment
- User asks about wrangler.toml configuration
Load
when:references/error-catalog.md
- Encountering any of the 15 documented errors
- User reports D1 adapter, schema, CORS, or OAuth issues
- User asks about troubleshooting or debugging
- User needs prevention checklist
Load
when:references/advanced-features.md
- User asks about 2FA, passkeys, or magic links
- User needs organizations, teams, or RBAC
- User asks about rate limiting or session management
- User wants migration guide from Clerk or Auth.js
- User needs security best practices or performance optimization
Load
when:references/v1.5-features.md
- User asks about the new CLI, MCP auth, OAuth 2.1 Provider
- User needs Electron desktop auth or i18n error translations
- User asks about dynamic base URL or secret key rotation
- User needs D1 native support (no adapter) or adapter extraction
- User asks about test utils, seat-based billing, or typed error codes
- User needs Cloudflare D1 native support configuration
Load
when:references/v1.6-features.md
- User asks about OpenTelemetry or distributed tracing
- User needs passkey pre-auth registration (before session)
- User asks about case-insensitive database queries
- User encounters session freshness issues after upgrading
- User asks about SAML InResponseTo validation
Load
when:references/migration-guide-1.5.0.md
- User upgrading from better-auth <1.5.0 to 1.5.0+
- User encounters API Key import errors (
→userId
)referenceId - User asks about after hooks running post-transaction
- User encounters
/InferUser
type errorsInferSession - User needs to update
imports@better-auth/core/utils
Load
when:references/plugins/sso.md
- User needs production SSO with OIDC, OAuth2, or SAML 2.0
- User asks about OIDC discovery, SAML SLO, or domain verification
- User needs organization provisioning via SSO
- User asks about SAML security (InResponseTo, replay protection, timestamps)
- User encounters SSO discovery errors
Load
when:references/plugins/test-utils.md
- User writing integration or E2E tests with Better Auth
- User needs test factories (createUser, createOrganization)
- User needs authenticated test sessions (login, getAuthHeaders, getCookies)
- User needs OTP capture for verification tests
Load
when:references/integrations/electron.md
- User building Electron desktop app with Better Auth
- User needs system browser OAuth flow for desktop
- User asks about deep links, custom protocol schemes
- User needs IPC bridges or manual token exchange
Load
when:references/cloudflare-worker-drizzle.ts
- User needs complete Worker implementation example
- User asks for production-ready code
- User wants to see full auth flow with protected routes
Load
when:references/cloudflare-worker-kysely.ts
- User prefers Kysely over Drizzle
- User asks for Kysely-specific implementation
Load
when:references/database-schema.ts
- User needs complete better-auth schema with all tables
- User asks about custom tables or schema extension
- User needs TypeScript types for database
Load
when:references/react-client-hooks.tsx
- User building React/Next.js frontend
- User needs login forms, session hooks, or protected routes
- User asks about client-side implementation
Load
when:references/configuration-guide.md
- User asks about production configuration
- User needs environment variable setup or wrangler.toml
- User asks about dynamic base URL, secret rotation, or D1 native
- User needs CORS configuration, rate limiting, or API keys
- User asks about session configuration (deferSessionRefresh, verification on secondary storage)
Load
when:references/framework-comparison.md
- User asks "better-auth vs Clerk" or "vs Auth.js"
- User needs help choosing auth framework
- User wants feature comparison, migration advice, or cost analysis
Load
when:references/migration-guide-1.4.0.md
- User upgrading from better-auth <1.4.0 to 1.4.0+
- User encounters
errors or ESM issuesforgetPassword - User asks about breaking changes or migration steps
Load
when:references/v1.4-features.md
- User asks about background tasks or deferred email sending
- User needs Patreon, Vercel, or Kick OAuth provider setup
- User asks about the better-auth CLI tool
- User needs admin role permissions configuration
Load
when:references/nextjs/README.md
- User building Next.js app with PostgreSQL (not Cloudflare D1)
- User needs organizations and 2FA example
- User asks about Next.js-specific implementation
Load
when:references/nextjs/postgres-example.ts
- User needs complete Next.js API route implementation
- User wants to see organizations + 2FA in practice
- User asks for PostgreSQL setup with Drizzle
Framework-Specific Setup
Load
when:references/frameworks/nextjs.md
- User building with Next.js (App Router or Pages Router)
- User needs middleware, Server Components, or API routes
Load
when:references/frameworks/nuxt.md
- User building with Nuxt 3
- User needs H3 handlers, composables, or server routes
Load
when:references/frameworks/remix.md
- User building with Remix
- User needs loader/action patterns or session handling
Load
when:references/frameworks/sveltekit.md
- User building with SvelteKit
- User needs hooks, load functions, or stores
Load
when:references/frameworks/api-frameworks.md
- User building with Express, Fastify, NestJS, or Hono (non-Cloudflare)
- User needs middleware or route configuration
Load
when:references/frameworks/expo-mobile.md
- User building React Native or Expo app
- User needs SecureStore, deep linking, or mobile auth
Database Adapters
Load
when:references/databases/postgresql.md
- User using PostgreSQL with Drizzle or Prisma
- User needs Neon, Supabase, or connection pooling setup
Load
when:references/databases/mongodb.md
- User using MongoDB
- User needs Atlas setup or indexes
Load
when:references/databases/mysql.md
- User using MySQL or PlanetScale
- User needs Vitess compatibility guidance
Plugin Guides
Load
when:references/plugins/authentication.md
- User needs 2FA, passkeys (incl. pre-auth), magic links, email OTP, or anonymous users
- User asks about enhanced authentication methods
Load
when:references/plugins/enterprise.md
- User needs organizations, SSO/SAML, SCIM, or admin dashboard
- User building multi-tenant or enterprise application
Load
when:references/plugins/api-tokens.md
- User needs API keys (incl. org-owned, multi-config), bearer tokens, JWT
- User building API authentication for third parties
Load
when:references/plugins/payments.md
- User needs Stripe (incl. seat-based billing) or Polar integration
- User building subscription or payment features
Load
when:references/plugins/sso.md
- User needs production SSO with OIDC, OAuth2, or SAML 2.0
- User asks about OIDC discovery, SAML SLO, domain verification
- User needs organization provisioning via SSO
Load
when:references/plugins/test-utils.md
- User writing integration or E2E tests
- User needs test factories, OTP capture, or authenticated sessions
Integration Guides
Load
when:references/integrations/electron.md
- User building Electron desktop app with Better Auth
- User needs system browser OAuth, deep links, IPC bridges
Configuration Reference
Quick Config (ESM-only in v1.4.0+):
export const auth = betterAuth({ baseURL: env.BETTER_AUTH_URL, secret: env.BETTER_AUTH_SECRET, database: drizzleAdapter(db, { provider: "sqlite" }), });
Load
for:references/configuration-guide.md
- Production configuration with email/password and social providers
- wrangler.toml setup and environment variables
- Session configuration, CORS setup, and ESM requirements
- Rate limiting, API keys (v1.4.0+), and troubleshooting
Using Bundled Resources
References (references/)
- setup-guide.md - Complete 8-step setup (D1 → Drizzle → Deploy)
- error-catalog.md - All 15 errors with solutions and prevention checklist
- advanced-features.md - 2FA, organizations, rate limiting, passkeys, magic links, migrations
- configuration-guide.md - Production config, dynamic base URL, secret rotation, D1 native
- framework-comparison.md - better-auth vs Clerk vs Auth.js, migration paths, TCO
- migration-guide-1.4.0.md - Upgrading from v1.3.x to v1.4.0+ (ESM, API changes)
- migration-guide-1.5.0.md - Upgrading from v1.4.x to v1.5.0+ (API Key, adapter imports, hooks)
- v1.4-features.md - Background tasks, new OAuth providers, SAML/SSO, CLI
- v1.5-features.md - New CLI, OAuth 2.1 Provider, Electron, i18n, D1 native, secret rotation
- v1.6-features.md - OpenTelemetry, passkey pre-auth, non-blocking scrypt
- cloudflare-worker-drizzle.ts - Complete Worker with Drizzle auth
- cloudflare-worker-kysely.ts - Complete Worker with Kysely auth
- database-schema.ts - Complete better-auth Drizzle schema
- react-client-hooks.tsx - React components with auth hooks
Framework References (references/frameworks/)
- nextjs.md - Next.js App/Pages Router integration
- nuxt.md - Nuxt 3 with H3 and composables
- remix.md - Remix loaders, actions, sessions
- sveltekit.md - SvelteKit hooks and stores
- api-frameworks.md - Express, Fastify, NestJS, Hono
- expo-mobile.md - React Native and Expo
Database References (references/databases/)
- postgresql.md - PostgreSQL with Drizzle/Prisma, Neon/Supabase
- mongodb.md - MongoDB adapter and Atlas
- mysql.md - MySQL and PlanetScale
Plugin References (references/plugins/)
- authentication.md - 2FA, passkeys (incl. pre-auth), magic links, email OTP, anonymous
- enterprise.md - Organizations, SSO, SCIM, admin
- api-tokens.md - API keys (incl. org-owned, multi-config), bearer tokens, JWT
- payments.md - Stripe, Polar integrations
- sso.md - Production SSO: OIDC discovery, SAML SLO, domain verification, security
- test-utils.md - Testing helpers: factories, OTP capture, login, Vitest/Playwright
Integration References (references/integrations/)
- electron.md - Electron desktop auth: system browser OAuth, IPC bridges, deep links
Next.js Examples (references/nextjs/)
- README.md - Next.js + PostgreSQL setup guide (not D1)
- postgres-example.ts - Complete API route with organizations, 2FA, email verification
Client Integration
Create auth client (
src/lib/auth-client.ts):
import { createAuthClient } from "better-auth/client"; export const authClient = createAuthClient({ baseURL: import.meta.env.VITE_API_URL || "http://localhost:8787", });
Use in React:
import { authClient } from "@/lib/auth-client"; export function UserProfile() { const { data: session, isPending } = authClient.useSession(); if (isPending) return <div>Loading...</div>; if (!session) return <div>Not authenticated</div>; return ( <div> <p>Welcome, {session.user.email}</p> <button onClick={() => authClient.signOut()}>Sign Out</button> </div> ); }
Dependencies
Required:
- Core authentication framework (ESM-only)better-auth@^1.6.0
Choose ONE adapter (optional with D1 native in v1.5+):
+drizzle-orm@^0.44.7
(recommended for complex schemas)drizzle-kit@^0.31.7
+kysely@^0.28.8
(alternative)@noxharmonium/kysely-d1@^0.4.0
+@better-auth/drizzle-adapter
(smallest bundle, v1.5+)better-auth/minimal
Optional:
- TypeScript types for Workers@cloudflare/workers-types
- Web framework for routinghono@^4.0.0
- Passkey/WebAuthn plugin@better-auth/passkey
- API key auth with org support@better-auth/api-key
- SSO/SAML/OIDC production plugin@better-auth/sso
- Electron desktop auth@better-auth/electron
- Error message translations@better-auth/i18n
- OAuth 2.1 authorization server@better-auth/oauth-provider
Beyond Cloudflare D1
This skill focuses on Cloudflare Workers + D1. better-auth also supports:
Frameworks (18 total): Next.js, Nuxt, Remix, SvelteKit, Astro, Express, NestJS, Fastify, Elysia, Expo, and more.
Databases (9 adapters): PostgreSQL, MongoDB, MySQL, Prisma, MS SQL, and others.
Additional Plugins: Anonymous auth, Email OTP, JWT, Multi-Session, OAuth 2.1 Provider, Test Utils, SCIM, payment integrations (Stripe, Polar), Device Authorization.
For non-Cloudflare setups, load the appropriate framework or database reference file, or consult the official docs: https://better-auth.com/docs
Official Documentation
- better-auth Docs: https://better-auth.com
- GitHub: https://github.com/better-auth/better-auth (22.4k ⭐)
- Examples: https://github.com/better-auth/better-auth/tree/main/examples
- Drizzle Docs: https://orm.drizzle.team/docs/get-started-sqlite
- Kysely Docs: https://kysely.dev/
- Discord: https://discord.gg/better-auth
Framework Comparison
Load
for:references/framework-comparison.md
- Complete feature comparison: better-auth vs Clerk vs Auth.js
- v1.4.0+ new features (database joins, stateless sessions, API keys)
- Migration paths, cost analysis, and performance benchmarks
- Recommendations by use case and 5-year TCO
Production Examples
Verified working repositories (all use Drizzle or Kysely):
- zwily/example-react-router-cloudflare-d1-drizzle-better-auth - Drizzle
- matthewlynch/better-auth-react-router-cloudflare-d1 - Kysely
- foxlau/react-router-v7-better-auth - Drizzle
- zpg6/better-auth-cloudflare - Drizzle (includes CLI)
Note: Check each repo's better-auth version. Repos on v1.3.x need v1.4.0+ migration (see
references/migration-guide-1.4.0.md). None use a direct d1Adapter - all require Drizzle/Kysely.
Complete Setup Checklist
- Verified ESM support (
in package.json) - v1.4.0+ required"type": "module" - Installed better-auth@1.6.0+ (D1 native) or + Drizzle/Kysely
- Created D1 database with wrangler
- Defined database schema (or using D1 native without schema)
- Generated and applied migrations to D1
- Set BETTER_AUTH_SECRET environment variable
- Configured baseURL in auth config (or dynamic base URL for previews)
- Enabled authentication methods (emailAndPassword, socialProviders)
- Configured CORS with credentials: true
- Set OAuth callback URLs in provider settings
- Tested auth routes (/api/auth/*)
- Tested sign-in, sign-up, session verification
- Using requestPasswordReset (not forgetPassword) - v1.4.0+ API
- Using
CLI (notnpx auth
) - v1.5.0+@better-auth/cli - Using
(not@better-auth/api-key
) for API keys - v1.5.0+better-auth/plugins - Deployed to Cloudflare Workers
Questions? Issues?
- Check
for all 15 errors and solutionsreferences/error-catalog.md - Review
for complete 8-step setupreferences/setup-guide.md - See
for 2FA, organizations, and morereferences/advanced-features.md - Check official docs: https://better-auth.com
- Ensure you're using Drizzle or Kysely (not non-existent d1Adapter)