🎯

better-auth

🎯Skill

from akornmeier/claude-config

VibeIndex|
What it does

Securely implement authentication and authorization with a framework-agnostic TypeScript library supporting email/password, OAuth, 2FA, and advanced auth features.

πŸ“¦

Part of

akornmeier/claude-config(24 items)

better-auth

Installation

npm installInstall npm package
npm install better-auth
npxRun with npx
npx @better-auth/cli generate
πŸ“– Extracted from docs: akornmeier/claude-config
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Guide for implementing Better Auth - a framework-agnostic authentication and authorization framework for TypeScript. Use when adding authentication features like email/password, OAuth, 2FA, passkeys, or advanced auth functionality to applications.

Overview

# Better Auth Skill

Better Auth is a comprehensive, framework-agnostic authentication and authorization framework for TypeScript that provides built-in support for email/password authentication, social sign-on, and a powerful plugin ecosystem for advanced features.

When to Use This Skill

Use this skill when:

  • Implementing authentication in TypeScript/JavaScript applications
  • Adding email/password or social OAuth authentication
  • Setting up 2FA, passkeys, magic links, or other advanced auth features
  • Building multi-tenant applications with organization support
  • Implementing session management and user management
  • Working with any framework (Next.js, Nuxt, SvelteKit, Remix, Astro, Hono, Express, etc.)

Core Concepts

Key Features

  • Framework Agnostic: Works with any framework (Next.js, Nuxt, Svelte, Remix, Hono, Express, etc.)
  • Built-in Auth Methods: Email/password and OAuth 2.0 social providers
  • Plugin Ecosystem: Easy-to-add advanced features (2FA, passkeys, magic link, username, email OTP, organization, etc.)
  • Database Flexibility: Supports SQLite, PostgreSQL, MySQL, MongoDB, and more
  • ORM Support: Built-in adapters for Drizzle, Prisma, Kysely, and MongoDB
  • Type Safety: Full TypeScript support with excellent type inference
  • Session Management: Built-in session handling for both client and server

Architecture

Better Auth follows a client-server architecture:

  1. Server Instance (better-auth): Handles auth logic, database operations, and API routes
  2. Client Instance (better-auth/client): Provides hooks and methods for authentication
  3. Plugins: Extend both server and client functionality

Installation & Setup

Step 1: Install Package

```bash

npm install better-auth

# or

pnpm add better-auth

# or

yarn add better-auth

# or

bun add better-auth

```

Step 2: Environment Variables

Create .env file:

```env

BETTER_AUTH_SECRET=

BETTER_AUTH_URL=http://localhost:3000

```

Generate secret: Use openssl or a random string generator (min 32 characters).

Step 3: Create Auth Server Instance

Create auth.ts in project root, lib/, utils/, or nested under src/, app/, or server/:

```ts

import { betterAuth } from 'better-auth';

export const auth = betterAuth({

database: {

// Database configuration

},

emailAndPassword: {

enabled: true,

autoSignIn: true, // Users auto sign-in after signup

},

socialProviders: {

github: {

clientId: process.env.GITHUB_CLIENT_ID!,

clientSecret: process.env.GITHUB_CLIENT_SECRET!,

},

google: {

clientId: process.env.GOOGLE_CLIENT_ID!,

clientSecret: process.env.GOOGLE_CLIENT_SECRET!,

},

},

});

```

Step 4: Database Configuration

Choose your database setup:

Direct Database Connection:

```ts

import { betterAuth } from 'better-auth';

import Database from 'better-sqlite3';

// or import { Pool } from "pg";

// or import { createPool } from "mysql2/promise";

export const auth = betterAuth({

database: new Database('./sqlite.db'),

// or: new Pool({ connectionString: process.env.DATABASE_URL })

// or: createPool({ host: "localhost", user: "root", ... })

});

```

ORM Adapter:

```ts

// Prisma

import { prismaAdapter } from 'better-auth/adapters/prisma';

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export const auth = betterAuth({

database: prismaAdapter(prisma, {

provider: 'postgresql',

}),

});

// Drizzle

import { drizzleAdapter } from 'better-auth/adapters/drizzle';

import { db } from '@/db';

export const auth = betterAuth({

database: drizzleAdapter(db, {

provider: 'pg', // or "mysql", "sqlite"

}),

});

// MongoDB

import { mongodbAdapter } from 'better-auth/adapters/mongodb';

import { client } from '@/db';

export const auth = betterAuth({

database: mongodbAdapter(client),

});

```

Step 5: Create Database Schema

Use Better Auth CLI:

```bash

# Generate schema/migration files

npx @better-auth/cli generate

# Or migrate directly (Kysely adapter only)

npx @better-auth/cli migrate

```

Step 6: Mount API Handler

Create catch-all route for /api/auth/*:

Next.js (App Router):

```ts

// app/api/auth/[...all]/route.ts

import { auth } from '@/lib/auth';

import { toNextJsHandler } from 'better-auth/next-js';

export const { POST, GET } = toNextJsHandler(auth);

```

Nuxt:

```ts

// server/api/auth/[...all].ts

import { auth } from '~/utils/auth';

export default defineEventHandler((event) => {

return auth.handler(toWebRequest(event));

});

```

SvelteKit:

```ts

// hooks.server.ts

import { auth } from '$lib/auth';

import { svelteKitHandler } from 'better-auth/svelte-kit';

export async function handle({ event, resolve }) {

return svelteKitHandler({ event, resolve, auth });

}

```

Hono:

```ts

import { Hono } from 'hono';

import { auth } from './auth';

const app = new Hono();

app.on(['POST', 'GET'], '/api/auth/*', (c) => auth.handler(c.req.raw));

```

Express:

```ts

import express from 'express';

import { toNodeHandler } from 'better-auth/node';

import { auth } from './auth';

const app = express();

app.all('/api/auth/*', toNodeHandler(auth));

```

Step 7: Create Client Instance

Create auth-client.ts:

```ts

import { createAuthClient } from 'better-auth/client';

export const authClient = createAuthClient({

baseURL: process.env.NEXT_PUBLIC_BETTER_AUTH_URL || 'http://localhost:3000',

});

```

Authentication Methods

Email & Password

Server Configuration:

```ts

export const auth = betterAuth({

emailAndPassword: {

enabled: true,

autoSignIn: true, // default: true

},

});

```

Client Usage:

```ts

// Sign Up

const { data, error } = await authClient.signUp.email(

{

email: 'user@example.com',

password: 'securePassword123',

name: 'John Doe',

image: 'https://example.com/avatar.jpg', // optional

callbackURL: '/dashboard', // optional

},

{

onSuccess: (ctx) => {

// redirect or show success

},

onError: (ctx) => {

alert(ctx.error.message);

},

}

);

// Sign In

const { data, error } = await authClient.signIn.email({

email: 'user@example.com',

password: 'securePassword123',

callbackURL: '/dashboard',

rememberMe: true, // default: true

});

```

Social OAuth

Server Configuration:

```ts

export const auth = betterAuth({

socialProviders: {

github: {

clientId: process.env.GITHUB_CLIENT_ID!,

clientSecret: process.env.GITHUB_CLIENT_SECRET!,

},

google: {

clientId: process.env.GOOGLE_CLIENT_ID!,

clientSecret: process.env.GOOGLE_CLIENT_SECRET!,

},

// Other providers: apple, discord, facebook, etc.

},

});

```

Client Usage:

```ts

await authClient.signIn.social({

provider: 'github',

callbackURL: '/dashboard',

errorCallbackURL: '/error',

newUserCallbackURL: '/welcome',

});

```

Sign Out

```ts

await authClient.signOut({

fetchOptions: {

onSuccess: () => {

router.push('/login');

},

},

});

```

Session Management

Client-Side Session

Using Hooks (React/Vue/Svelte/Solid):

```tsx

// React

import { authClient } from "@/lib/auth-client";

export function UserProfile() {

const { data: session, isPending, error } = authClient.useSession();

if (isPending) return

Loading...
;

if (error) return

Error: {error.message}
;

return

Welcome, {session?.user.name}!
;

}

// Vue

// Svelte

{$session.data?.user.email}

```

Using getSession:

```ts

const { data: session, error } = await authClient.getSession();

```

Server-Side Session

```ts

// Next.js

import { auth } from './auth';

import { headers } from 'next/headers';

const session = await auth.api.getSession({

headers: await headers(),

});

// Hono

app.get('/protected', async (c) => {

const session = await auth.api.getSession({

headers: c.req.raw.headers,

});

if (!session) {

return c.json({ error: 'Unauthorized' }, 401);

}

return c.json({ user: session.user });

});

```

Plugin System

Better Auth's plugin system allows adding advanced features easily.

Using Plugins

Server-Side:

```ts

import { betterAuth } from 'better-auth';

import { twoFactor, organization, username } from 'better-auth/plugins';

export const auth = betterAuth({

plugins: [twoFactor(), organization(), username()],

});

```

Client-Side:

```ts

import { createAuthClient } from 'better-auth/client';

import { twoFactorClient, organizationClient, usernameClient } from 'better-auth/client/plugins';

export const authClient = createAuthClient({

plugins: [

twoFactorClient({

twoFactorPage: '/two-factor',

}),

organizationClient(),

usernameClient(),

],

});

```

After Adding Plugins:

```bash

# Regenerate schema

npx @better-auth/cli generate

# Apply migration

npx @better-auth/cli migrate

```

Popular Plugins

#### Two-Factor Authentication (2FA)

```ts

// Server

import { twoFactor } from 'better-auth/plugins';

export const auth = betterAuth({

plugins: [twoFactor()],

});

// Client

import { twoFactorClient } from 'better-auth/client/plugins';

export const authClient = createAuthClient({

plugins: [twoFactorClient({ twoFactorPage: '/two-factor' })],

});

// Usage

await authClient.twoFactor.enable({ password: 'userPassword' });

await authClient.twoFactor.verifyTOTP({

code: '123456',

trustDevice: true,

});

```

#### Username Authentication

```ts

// Server

import { username } from 'better-auth/plugins';

export const auth = betterAuth({

plugins: [username()],

});

// Client

import { usernameClient } from 'better-auth/client/plugins';

// Sign up with username

await authClient.signUp.username({

username: 'johndoe',

password: 'securePassword123',

name: 'John Doe',

});

```

#### Magic Link

```ts

import { magicLink } from 'better-auth/plugins';

export const auth = betterAuth({

plugins: [

magicLink({

sendMagicLink: async ({ email, url }) => {

// Send email with magic link

await sendEmail(email, url);

},

}),

],

});

```

#### Passkey (WebAuthn)

```ts

import { passkey } from 'better-auth/plugins';

export const auth = betterAuth({

plugins: [passkey()],

});

// Client

await authClient.passkey.register();

await authClient.passkey.signIn();

```

#### Organization/Multi-Tenancy

```ts

import { organization } from 'better-auth/plugins';

export const auth = betterAuth({

plugins: [organization()],

});

// Client

await authClient.organization.create({

name: 'Acme Corp',

slug: 'acme',

});

await authClient.organization.inviteMember({

organizationId: 'org-id',

email: 'user@example.com',

role: 'member',

});

```

Advanced Configuration

Email Verification

```ts

export const auth = betterAuth({

emailVerification: {

sendVerificationEmail: async ({ user, url }) => {

await sendEmail(user.email, url);

},

sendOnSignUp: true,

},

});

```

Rate Limiting

```ts

export const auth = betterAuth({

rateLimit: {

enabled: true,

window: 60, // seconds

max: 10, // requests

},

});

```

Custom Session Expiration

```ts

export const auth = betterAuth({

session: {

expiresIn: 60 60 24 * 7, // 7 days in seconds

updateAge: 60 60 24, // Update every 24 hours

},

});

```

CORS Configuration

```ts

export const auth = betterAuth({

advanced: {

corsOptions: {

origin: ['https://example.com'],

credentials: true,

},

},

});

```

Database Schema

Core Tables

Better Auth requires these core tables:

  • user: User accounts
  • session: Active sessions
  • account: OAuth provider connections
  • verification: Email verification tokens

Auto-generate with CLI:

```bash

npx @better-auth/cli generate

```

Manual schema available in docs: Check /docs/concepts/database#core-schema

Best Practices

  1. Environment Variables: Always use environment variables for secrets
  2. HTTPS in Production: Set BETTER_AUTH_URL to HTTPS URL
  3. Session Security: Use secure cookies in production
  4. Error Handling: Implement proper error handling on client and server
  5. Type Safety: Leverage TypeScript types for better DX
  6. Plugin Order: Some plugins depend on others, check documentation
  7. Database Migrations: Always run migrations after adding plugins
  8. Rate Limiting: Enable rate limiting for production
  9. Email Verification: Implement email verification for security
  10. Password Requirements: Customize password validation as needed

Common Patterns

Protected Routes (Server-Side)

```ts

// Next.js middleware

import { auth } from '@/lib/auth';

import { NextRequest, NextResponse } from 'next/server';

export async function middleware(request: NextRequest) {

const session = await auth.api.getSession({

headers: request.headers,

});

if (!session) {

return NextResponse.redirect(new URL('/login', request.url));

}

return NextResponse.next();

}

export const config = {

matcher: ['/dashboard/:path*'],

};

```

User Profile Updates

```ts

await authClient.updateUser({

name: 'New Name',

image: 'https://example.com/new-avatar.jpg',

});

```

Password Management

```ts

// Change password

await authClient.changePassword({

currentPassword: 'oldPassword',

newPassword: 'newPassword',

});

// Reset password (forgot password)

await authClient.forgetPassword({

email: 'user@example.com',

redirectTo: '/reset-password',

});

await authClient.resetPassword({

token: 'reset-token',

password: 'newPassword',

});

```

Troubleshooting

Common Issues

  1. "Unable to find auth instance"

- Ensure auth.ts is in correct location (root, lib/, utils/)

- Export auth instance as auth or default export

  1. Database connection errors

- Verify database credentials

- Check if database server is running

- Ensure correct adapter for your database

  1. CORS errors

- Configure corsOptions in advanced settings

- Ensure client and server URLs match

  1. Plugin not working

- Run migrations after adding plugins

- Check plugin is added to both server and client

- Verify plugin configuration

Framework-Specific Guides

  • Next.js: Use Next.js plugin for server actions
  • Nuxt: Configure server middleware
  • SvelteKit: Use hooks.server.ts
  • Astro: Set up API routes properly
  • Hono/Express: Use appropriate node handlers

Resources

  • Documentation: https://www.better-auth.com/docs
  • GitHub: https://github.com/better-auth/better-auth
  • Plugins: https://www.better-auth.com/docs/plugins
  • Examples: https://www.better-auth.com/docs/examples

Implementation Checklist

When implementing Better Auth:

  • [ ] Install better-auth package
  • [ ] Set up environment variables (SECRET, URL)
  • [ ] Create auth server instance
  • [ ] Configure database/adapter
  • [ ] Run schema migration
  • [ ] Configure authentication methods
  • [ ] Mount API handler
  • [ ] Create client instance
  • [ ] Implement sign-up/sign-in UI
  • [ ] Add session management
  • [ ] Set up protected routes
  • [ ] Add plugins as needed
  • [ ] Test authentication flow
  • [ ] Configure email sending (if needed)
  • [ ] Set up error handling
  • [ ] Enable rate limiting for production

More from this repository10

🎯
postgresql-psql🎯Skill

Enables interactive PostgreSQL database management through psql, executing queries, scripting, and administering database operations from the command line.

🎯
shadcn-ui🎯Skill

Provides customizable, accessible React UI components using Tailwind CSS that can be directly copied and modified in your project.

🎯
openspec-dev🎯Skill

Automates OpenSpec change implementation by parsing tasks, filtering phases, and creating PRs using subagent-driven development.

🎯
cloudflare-workers🎯Skill

Enables building and deploying serverless edge functions across Cloudflare's global network using JavaScript, TypeScript, Python, and Rust.

🎯
mongodb🎯Skill

Enables comprehensive MongoDB database management, from schema design and querying to deployment, performance optimization, and secure integration across multiple platforms and languages.

🎯
turborepo🎯Skill

Accelerates monorepo development by enabling intelligent caching, parallel task execution, and efficient build performance across JavaScript and TypeScript projects.

🎯
cloudflare-r2🎯Skill

Enables seamless S3-compatible object storage on Cloudflare's global network with zero egress fees, supporting file uploads, downloads, and migrations.

🎯
nuxt-ui-tdd🎯Skill

Guides developers in building Vue 3 NuxtUI components using strict Test-Driven Development (TDD) methodology with atomic design principles and Storybook interaction tests.

🎯
skill-creator🎯Skill

Generates configurable AI skills with customizable parameters and templates for Claude-based applications.

🎯
prd-to-ux🎯Skill

Translates product requirements into comprehensive UX specifications by systematically analyzing user mental models, information architecture, and interaction design.