secondsky/claude-skillsMIT38 files

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.

Specification
Skill ID
secondsky/claude-skills/better-auth
Publisher
secondsky
Repository
claude-skills
Installs
0
Files
38
License
MIT
Synced
Sep 23, 2026
How to use it

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-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](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/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 `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

VariablePurposeExample
BETTER_AUTH_SECRETEncryption secret (min 32 chars)Generate: openssl rand -base64 32
BETTER_AUTH_URLBase URLhttps://example.com or http://localhost:8787
DATABASE_URLDatabase 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+)

CommandPurpose
npx auth initInteractive project scaffolding
npx auth migrateRun database migrations
npx auth generateGenerate auth schema
npx auth generate --adapter drizzleAdapter-specific schema
npx auth upgradeUpgrade to latest version
bunx drizzle-kit generateD1: Use this to generate Drizzle migrations
wrangler d1 migrations apply DB_NAMED1: Use this to apply migrations

Re-run after adding/changing plugins.

Core Config Options

| Option | Notes |

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.

Use this skill