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.
- Skill ID
- secondsky/claude-skills/better-auth
- Publisher
- secondsky
- Repository
- claude-skills
- Installs
- 0
- Files
- 38
- License
- MIT
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
secondsky/claude-skills/better-authInstalls these files- SKILL.md
- assets/auth-flow-diagram.md
- references/advanced-features.md
- references/cloudflare-worker-drizzle.ts
- references/cloudflare-worker-kysely.ts
- references/configuration-guide.md
- references/database-schema.ts
- references/databases/mongodb.md
- references/databases/mysql.md
- references/databases/postgresql.md
- references/error-catalog.md
- references/framework-comparison.md
- references/frameworks/api-frameworks.md
- references/frameworks/expo-mobile.md
- references/frameworks/nextjs.md
- references/frameworks/nuxt.md
- references/frameworks/remix.md
- references/frameworks/sveltekit.md
- references/integrations/electron.md
- references/migration-guide-1.4.0.md
- references/migration-guide-1.5.0.md
- references/nextjs/README.md
- references/nextjs/postgres-example.ts
- references/plugins/api-tokens.md
- references/plugins/authentication.md
- references/plugins/enterprise.md
- references/plugins/payments.md
- references/plugins/sso.md
- references/plugins/test-utils.md
- references/react-client-hooks.tsx
- references/setup-guide.md
- references/v1.4-features.md
- references/v1.5-features.md
- references/v1.6-features.md
- scripts/generate-secret.sh
- scripts/setup-d1-drizzle.sh
- scripts/test-auth-health.sh
- scripts/validate-config.ts
What this skill tells the agent
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-kitOption 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-db2. 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 schema3. 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 deployDecision Tree
For code examples and syntax, always consult [better-auth.com/docs](https://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/componentsCritical 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 `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/electronfor desktop apps - i18n:
@better-auth/i18nfor 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
codein 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 |
More from secondsky
Use this skill in a project
Open any RiverX project, search the Skills panel for secondsky/claude-skills/better-auth, and install it in one click.
