better-auth

Installation
SKILL.md

better-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: userIdreferenceId, new configId field.

After Hooks: Database after-hooks now run post-transaction (not inside it).

Deprecated APIs Removed: AdapterDBAdapter, InferUser/InferSession removed, @better-auth/core/utils split into subpath exports.

Load references/migration-guide-1.5.0.md when upgrading from <1.5.0

⚠️ 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: @better-auth/oauth-provider (MCP-ready)
  • Electron: @better-auth/electron for desktop apps
  • i18n: @better-auth/i18n for error translations
  • 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 code in error responses

Load references/v1.5-features.md for detailed implementation guides.

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: mode: "insensitive" on adapter queries

Load references/v1.6-features.md for detailed implementation guides.


Quick Reference

Environment Variables

Variable Purpose Example
BETTER_AUTH_SECRET Encryption secret (min 32 chars) Generate: openssl rand -base64 32
BETTER_AUTH_URL Base URL https://example.com or http://localhost:8787
DATABASE_URL 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
npx auth init Interactive project scaffolding
npx auth migrate Run database migrations
npx auth generate Generate auth schema
npx auth generate --adapter drizzle Adapter-specific schema
npx auth upgrade Upgrade to latest version
bunx drizzle-kit generate D1: Use this to generate Drizzle migrations
wrangler d1 migrations apply DB_NAME D1: Use this to apply migrations

Re-run after adding/changing plugins.

Core Config Options

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 (min 32 chars)
database Required for most features. Use drizzleAdapter() or Kysely for D1
secondaryStorage Redis/KV for sessions & rate limits
emailAndPassword { enabled: true } to activate
socialProviders { google: { clientId, clientSecret }, ... }
plugins Array of plugins (import from dedicated paths)
trustedOrigins 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 references/error-catalog.md for all 15 errors with detailed solutions.


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 references/setup-guide.md when:

  • 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 references/error-catalog.md when:

  • 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 references/advanced-features.md when:

  • 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 references/v1.5-features.md when:

  • 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 references/v1.6-features.md when:

  • 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 references/migration-guide-1.5.0.md when:

  • User upgrading from better-auth <1.5.0 to 1.5.0+
  • User encounters API Key import errors (userIdreferenceId)
  • User asks about after hooks running post-transaction
  • User encounters InferUser/InferSession type errors
  • User needs to update @better-auth/core/utils imports

Load references/plugins/sso.md when:

  • 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 references/plugins/test-utils.md when:

  • 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 references/integrations/electron.md when:

  • 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 references/cloudflare-worker-drizzle.ts when:

  • User needs complete Worker implementation example
  • User asks for production-ready code
  • User wants to see full auth flow with protected routes

Load references/cloudflare-worker-kysely.ts when:

  • User prefers Kysely over Drizzle
  • User asks for Kysely-specific implementation

Load references/database-schema.ts when:

  • User needs complete better-auth schema with all tables
  • User asks about custom tables or schema extension
  • User needs TypeScript types for database

Load references/react-client-hooks.tsx when:

  • User building React/Next.js frontend
  • User needs login forms, session hooks, or protected routes
  • User asks about client-side implementation

Load references/configuration-guide.md when:

  • 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 references/framework-comparison.md when:

  • 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 references/migration-guide-1.4.0.md when:

  • User upgrading from better-auth <1.4.0 to 1.4.0+
  • User encounters forgetPassword errors or ESM issues
  • User asks about breaking changes or migration steps

Load references/v1.4-features.md when:

  • 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 references/nextjs/README.md when:

  • User building Next.js app with PostgreSQL (not Cloudflare D1)
  • User needs organizations and 2FA example
  • User asks about Next.js-specific implementation

Load references/nextjs/postgres-example.ts when:

  • 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 references/frameworks/nextjs.md when:

  • User building with Next.js (App Router or Pages Router)
  • User needs middleware, Server Components, or API routes

Load references/frameworks/nuxt.md when:

  • User building with Nuxt 3
  • User needs H3 handlers, composables, or server routes

Load references/frameworks/remix.md when:

  • User building with Remix
  • User needs loader/action patterns or session handling

Load references/frameworks/sveltekit.md when:

  • User building with SvelteKit
  • User needs hooks, load functions, or stores

Load references/frameworks/api-frameworks.md when:

  • User building with Express, Fastify, NestJS, or Hono (non-Cloudflare)
  • User needs middleware or route configuration

Load references/frameworks/expo-mobile.md when:

  • User building React Native or Expo app
  • User needs SecureStore, deep linking, or mobile auth

Database Adapters

Load references/databases/postgresql.md when:

  • User using PostgreSQL with Drizzle or Prisma
  • User needs Neon, Supabase, or connection pooling setup

Load references/databases/mongodb.md when:

  • User using MongoDB
  • User needs Atlas setup or indexes

Load references/databases/mysql.md when:

  • User using MySQL or PlanetScale
  • User needs Vitess compatibility guidance

Plugin Guides

Load references/plugins/authentication.md when:

  • User needs 2FA, passkeys (incl. pre-auth), magic links, email OTP, or anonymous users
  • User asks about enhanced authentication methods

Load references/plugins/enterprise.md when:

  • User needs organizations, SSO/SAML, SCIM, or admin dashboard
  • User building multi-tenant or enterprise application

Load references/plugins/api-tokens.md when:

  • User needs API keys (incl. org-owned, multi-config), bearer tokens, JWT
  • User building API authentication for third parties

Load references/plugins/payments.md when:

  • User needs Stripe (incl. seat-based billing) or Polar integration
  • User building subscription or payment features

Load references/plugins/sso.md when:

  • 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 references/plugins/test-utils.md when:

  • User writing integration or E2E tests
  • User needs test factories, OTP capture, or authenticated sessions

Integration Guides

Load references/integrations/electron.md when:

  • 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 references/configuration-guide.md for:

  • 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:

  • better-auth@^1.6.0 - Core authentication framework (ESM-only)

Choose ONE adapter (optional with D1 native in v1.5+):

  • drizzle-orm@^0.44.7 + drizzle-kit@^0.31.7 (recommended for complex schemas)
  • kysely@^0.28.8 + @noxharmonium/kysely-d1@^0.4.0 (alternative)
  • @better-auth/drizzle-adapter + better-auth/minimal (smallest bundle, v1.5+)

Optional:

  • @cloudflare/workers-types - TypeScript types for Workers
  • hono@^4.0.0 - Web framework for routing
  • @better-auth/passkey - Passkey/WebAuthn plugin
  • @better-auth/api-key - API key auth with org support
  • @better-auth/sso - SSO/SAML/OIDC production plugin
  • @better-auth/electron - Electron desktop auth
  • @better-auth/i18n - Error message translations
  • @better-auth/oauth-provider - OAuth 2.1 authorization server

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


Framework Comparison

Load references/framework-comparison.md for:

  • 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):

  1. zwily/example-react-router-cloudflare-d1-drizzle-better-auth - Drizzle
  2. matthewlynch/better-auth-react-router-cloudflare-d1 - Kysely
  3. foxlau/react-router-v7-better-auth - Drizzle
  4. 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 ("type": "module" in package.json) - v1.4.0+ required
  • 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 npx auth CLI (not @better-auth/cli) - v1.5.0+
  • Using @better-auth/api-key (not better-auth/plugins) for API keys - v1.5.0+
  • Deployed to Cloudflare Workers

Questions? Issues?

  1. Check references/error-catalog.md for all 15 errors and solutions
  2. Review references/setup-guide.md for complete 8-step setup
  3. See references/advanced-features.md for 2FA, organizations, and more
  4. Check official docs: https://better-auth.com
  5. Ensure you're using Drizzle or Kysely (not non-existent d1Adapter)
Weekly Installs
190
GitHub Stars
126
First Seen
Today