Back to 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.

typescriptcloudflare
By secondsky
21030Updated 5 days agoTypeScriptMIT

Skill Content

# 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)**
```bash
bun add better-auth drizzle-orm drizzle-kit
```

**Option 2: Kysely**
```bash
bun add better-auth kysely @noxharmonium/kysely-d1
```

### ⚠️ v1.4.0+ Requirements

better-auth v1.4.0+ is **ESM-only**. Ensure:

**package.json**:
```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:

```typescript
// ✅ 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:
```typescript
// ✅ 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" }),
});
```

```typescript
// ❌ WRONG - This doesn't exist
import { d1Adapter } from 'better-auth/adapters/d1'
```

### Minimal Setup (Cloudflare Workers + Drizzle)

**1. Create D1 Database:**
```bash
wrangler d1 create my-app-db
```

**2. Define Schema** (`src/db/schema.ts`):
```typescript
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`):
```typescript
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`):
```typescript
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:**
```bash
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**:
```typescript
- 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

| 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+):
```typescript
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**:
```typescript
// 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**:
```typescript
// 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**:
```typescript
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 (`userId` → `referenceId`)
- 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+):
```typescript
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`):
```typescript
import { createAuthClient } from "better-auth/client";

export const authClient = createAuthClient({
  baseURL: import.meta.env.VITE_API_URL || "http://localhost:8787",
});
```

**Use in React**:
```typescript
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

- **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 `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.

---

## Secure Installation

When installing authentication packages, follow supply chain security best practices — auth libraries are high-value targets for supply chain attacks:

- **Block post-install scripts** — `npm config set ignore-scripts true` (or Bun: disabled by default)
- **Cooldown period** — Wait 7 days for new package versions to be vetted by the community
- **Audit before installing** — Run `socket package score npm <pkg>` or use `socket npm install <pkg>` to check packages

Load the `dependency-upgrade` skill for full security configuration including Socket CLI integration, cooldown setup, lockfile validation, and CI enforcement.

## 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)

How to use

  1. Copy the skill content above
  2. Create a .claude/skills/claude-skills-better-auth directory in your project (or ~/.claude/skills/claude-skills-better-auth to use it in every project)
  3. Save the content as .claude/skills/claude-skills-better-auth/SKILL.md
  4. Claude Code loads it automatically when the task matches, or run /claude-skills-better-auth to invoke it directly

Claude Code Skills Collection

142 production-ready skills for Claude Code CLI

Version 3.6.3 | Last Updated: 2026-08-06

<div align="center">

🔌 Platform / Harness Support

These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests). Other harnesses consume the same skills via skills.sh — the cross-harness bridge.

HarnessMarketplace supportHow to install
Claude CodeNative (federated)/plugin marketplace add secondsky/claude-skills, then /plugin install <name>@claude-skills
ZCodeNative (reads .claude-plugin/ manifests)Add this repo as a marketplace in the ZCode GUI
Codex CLINative (federated)codex plugin marketplace add secondsky/claude-skills, then /plugins in the Codex TUI
Cursor⚠️ Adaptation neededCursor has an official marketplace, but expects .cursor-plugin/plugin.json (UI "Add to Cursor") this repo does not generate yet. Use skills.sh.
opencode❌ No marketplacenpm plugins only (opencode.json plugin[]). Use skills.sh or vendor manually.
Gemini CLI❌ No marketplacegemini extensions install <url> only. Use skills.sh or vendor manually.
</div>

A curated collection of battle-tested skills for building modern web applications with Cloudflare, AI integrations, React, Tailwind, and more.


Quick Start

Marketplace Installation (Recommended)

# Add the marketplace
/plugin marketplace add https://github.com/secondsky/claude-skills

# Install individual skills as needed
/plugin install cloudflare-d1@claude-skills
/plugin install tailwind-v4-shadcn@claude-skills
/plugin install gemini-cli@claude-skills

See MARKETPLACE.md for complete catalog of all 142 skills.

Codex CLI Installation

This repo generates .codex-plugin/ manifests and a .agents/plugins/marketplace.json for all 142 plugins, so Codex CLI can install them natively:

# Add the marketplace (from GitHub)
codex plugin marketplace add secondsky/claude-skills

# Browse and install plugins in the Codex TUI
#   /plugins          # opens the plugin browser
#   Space             # enable/disable a plugin

Skills are auto-discovered from each plugin's skills/ directory — the same SKILL.md files Claude Code uses. Claude-specific slash commands and subagents are not carried into Codex (use Codex's /import command for that).


Installing with skills.sh

skills.sh is an open agent-skills registry and npx skills CLI (maintained by Vercel) that auto-detects your coding agent — Claude Code, Cursor, Codex, Copilot, Cline, opencode, and 70+ others — and installs each skill into the correct directory for that harness. It is the universal cross-harness path for harnesses without a marketplace (opencode, Gemini CLI) or where this repo's manifest format isn't generated yet (Cursor).

# Install one skill (auto-detects your agent)
npx skills add secondsky/claude-skills --skill cloudflare-d1

# Install several specific skills
npx skills add secondsky/claude-skills --skill cloudflare-d1 --skill tailwind-v4-shadcn

# Try a skill once without installing (pipes its prompt to your agent)
npx skills use secondsky/claude-skills@cloudflare-d1 | claude

# Target a specific agent explicitly
npx skills add secondsky/claude-skills --skill cloudflare-d1 --agent codex

# List what's installed, search, update, remove
npx skills ls -g
npx skills find cloudflare
npx skills update cloudflare-d1
npx skills remove cloudflare-d1

Bulk install note: npx skills add secondsky/claude-skills --all installs every discovered skill at once, but discovery walks skills.sh's standard container directories (skills/, .claude/skills/, …). This repo nests skills under plugins/<name>/skills/<skill>/, so --all may not pick up everything in one pass — install the skills you need by name with --skill, or run npx skills add secondsky/claude-skills -l to list what it finds.

Security scanning caveat

skills.sh runs every published skill through three scanners (Gen Agent Trust Hub, Socket, Snyk) plus an LLM-based meta-analyzer, and publishes the results at skills.sh/audits. The LLM analysis stage has been publicly shown (Trail of Bits, June 2026) to both miss genuinely malicious skills and flag unfamiliar version pins (e.g. newest dependency versions) as suspicious false positives. Treat skills.sh warnings as advisory, not authoritative — and verify against this repo's own version pins before acting on a warning.


Repository Structure

This repository contains 142 production-tested skills for Claude Code, each focused on a specific technology or capability.

Individual Skills: Each skill is a standalone unit with:

  • SKILL.md - Core knowledge and guidance
  • Templates - Working code examples
  • References - Extended documentation
  • Scripts - Helper utilities

Installation Options:

  1. Marketplace (recommended) - Install individual skills via /plugin install <name>@claude-skills
  2. Cross-harness - Install into any supported agent with npx skills add secondsky/claude-skills --skill <name> (see Installing with skills.sh)

Available Skills (142 Individual Skills)

Each skill is individually installable. Install only the skills you need.

Full Catalog: See MARKETPLACE.md for detailed listings.

Categories

CategorySkillsExamples
tooling24turborepo, plan-interview, code-review
frontend26nuxt-v4, nuxt-v5, tailwind-v4-shadcn, tanstack-query, nuxt-studio, maz-ui, threejs
cloudflare21cloudflare-d1, cloudflare-workers-ai, cloudflare-agents
api16api-design-principles, graphql-implementation
ai7gemini-cli, ml-model-training, tanstack-ai
web10hono-routing, firecrawl-scraper, web-performance
security6csrf-protection, xss-prevention, cybersecurity
mobile5react-native-app, react-native-skills
woocommerce4woocommerce-backend-dev
testing4vitest-testing, playwright-testing
design4design-review, design-system-creation
auth4better-auth
architecture3microservices-patterns, architecture-patterns
data2recommendation-engine, recommendation-system
cms2hugo, wordpress-plugin-core
database1drizzle-orm-d1
seo2seo-optimizer, seo-keyword-cluster-builder
documentation1technical-specification

How It Works

Auto-Discovery

Claude Code automatically checks ~/.claude/skills/ for relevant skills before planning tasks:

User: "Set up a Cloudflare Worker with D1 database"
           ↓
Claude: [Checks skills automatically]
           ↓
Claude: "Found cloudflare-d1 skills.
         These prevent 12 documented errors. Use them?"
           ↓
User: "Yes"
           ↓
Result: Production-ready setup, zero errors, ~65% token savings

Note: Due to token limits, not all skills may be visible at once. See ⚠️ Important: Token Limits below.

Skill Structure

Each plugin is a directory under plugins/<plugin-name>/ containing one or more skills:

plugins/[plugin-name]/
├── .claude-plugin/
│   └── plugin.json       # Plugin manifest (marketplace metadata)
├── README.md
├── skills/
│   └── [skill-name]/
│       ├── SKILL.md          # Core knowledge and guidance
│       ├── templates/        # Ready-to-copy templates
│       ├── scripts/          # Helper utilities
│       └── references/       # Extended documentation
└── (optional) agents/, commands/, hooks/

Recent Additions

July 2026

Offensive Security (new category):

  • cybersecurity — Unified OSS-only cybersecurity skill with progressive disclosure. Fuses 7 community skills (mukul975 business-logic/XSS/host-header/forced-browsing/open-redirect, rysweet/amplihack cybersecurity-analyst, Aradotso security-detections-mcp) ported to fully open-source tooling (OWASP ZAP, Dalfox, ffuf, Nuclei, mitmproxy, interact.sh, Semgrep, Sigma). Covers threat modeling (STRIDE/PASTA/VAST, MITRE ATT&CK), web-vuln testing, SAST, code audit, AI/LLM-app security, and detection engineering. Live-target testing is gated behind an authorization disclaimer; static analysis, code review, and threat modeling are always available. Cross-references the 5 existing defensive security plugins (csrf-protection, xss-prevention, vulnerability-scanning, security-headers-configuration, defense-in-depth-validation) for remediation. Integrates 20 Aradotso dev-security skills across 5 grouped reference docs.

May 2026

Supply Chain Security (cross-cutting):

  • dependency-upgrade expanded with Socket CLI integration — proactive malicious package detection, typosquatting alerts, and CI/CD security gates. New 418-line reference guide, 2 GitHub Actions templates, and expanded supply chain security comparison (3 tools)
  • 31 skills now include "Secure Installation" guidance — contextually-tailored security sections across all high-risk skill categories (scaffolding, MCP/agent SDKs, multi-provider installs, Docker, CI/CD). Covers 8 Bun skills, 5 Nuxt skills, 6 Cloudflare skills, 4 AI/agent skills, and 8 frontend/tooling skills
  • Supply chain security is now a first-class cross-cutting concern woven into the skill collection — not a standalone topic

February - April 2026

Full-Stack Frameworks:

  • nuxt-v5 (v1.0.0) - Full Nuxt 5 support with 4 skills (core, data, server, production), 3 diagnostic agents, and interactive setup wizard
  • threejs (v1.0.0) - 3D web graphics: scenes, geometries, shaders, animations, post-processing

Infrastructure:

  • JSON schema validation - Automated plugin.json validation with CI support
  • GitHub issue templates - Skill-specific issue templates for bug reports, feature requests, and submissions

Plugin Enhancements:

  • mutation-testing - Added Bun native runner support
  • dependency-upgrade - Added supply chain security content

December 2025 - January 2026

Frontend Expansion:

  • nuxt-studio (v1.0.0) - Visual CMS for Nuxt Content with live preview, OAuth auth, and R2 storage integration
  • maz-ui (v1.0.0) - 50+ Vue/Nuxt components with theming, i18n, form generation, and 14 composables

Developer Workflow:

  • plan-interview (v2.0.0) - Adaptive interview-driven spec generation with autonomous quality review
  • turborepo (v2.8.0) - Updated to official Vercel skill with enhanced monorepo build optimization

Mobile Development:

  • react-native-skills (v1.0.0) - React Native & Expo best practices with performance optimization patterns

Enhanced Authentication:

  • better-auth (v2.2.0) - Expanded to 18 framework integrations with 30+ authentication plugins

⚠️ Important: Token Limits

Skill Visibility Constraint

Claude Code has a 15,000 character limit for the total size of skill descriptions in the system prompt. This limit also applies to commands and agents.

What this means:

  • Not all 142 skills may be visible in Claude's context at once
  • Skills are loaded based on relevance and available token budget
  • You can verify how many skills Claude currently sees by asking: "How many skills do you see in your system prompt?"

Checking Visible Skills

To verify which skills are currently loaded:

# Ask Claude Code directly
"Check what skills/plugins you see in your system prompt"

Claude will report something like: "85 of 142 skills visible due to token limits"

Workaround: Increase Token Budget

You can double the headroom for s

View source on GitHub