Source profileQuality 90/100Review permissions

einverne/dotfiles/claude/skills/better-auth/SKILL.md

better-auth

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.

Source repository stars
119
Declared platforms
0
Static risk flags
3
Last source update
2026-08-05
Source checked
2026-08-05

Decision brief

What it does—and where it fits

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.

Best for

  • Implementing authentication in TypeScript/JavaScript applications
  • Adding email/password or social OAuth authentication
  • Setting up 2FA, passkeys, magic links, or other advanced auth features

Not for

  • "Unable to find auth instance"
  • Ensure auth.ts is in correct location (root, lib/, utils/)

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/einverne/dotfiles --skill "claude/skills/better-auth"
Safe inspection promptEditorial

Inspect the Agent Skill "better-auth" from https://github.com/einverne/dotfiles/blob/7d18cf4fefdeec05853c7420cc0499dde1e88b27/claude/skills/better-auth/SKILL.md at commit 7d18cf4fefdeec05853c7420cc0499dde1e88b27. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Installation & Setup

    bash npm install better-auth

    bash npm install better-auth
  2. 02

    Step 1: Install Package

    bash npm install better-auth

    bash npm install better-auth
  3. 03

    Step 2: Environment Variables

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

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

    Step 3: Create Auth Server Instance

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

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

    Step 4: Database Configuration

    Choose your database setup:

    Choose your database setup:Direct Database Connection:

Permission review

Static risk signals and limitations

Runs scripts

medium · line 40

The documentation asks the agent to run terminal commands or scripts.

npm install better-auth

Runs scripts

medium · line 42

The documentation asks the agent to run terminal commands or scripts.

pnpm add better-auth

Writes files

medium · line 51

The documentation asks the agent to create, modify, or delete local files.

Create `.env` file:

Network access

medium · line 55

The documentation includes network, browsing, or remote request actions.

BETTER_AUTH_URL=http://localhost:3000

Network access

medium · line 213

The documentation includes network, browsing, or remote request actions.

baseURL: process.env.NEXT_PUBLIC_BETTER_AUTH_URL || "http://localhost:3000"

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score90/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars119SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
einverne/dotfiles
Skill path
claude/skills/better-auth/SKILL.md
Commit
7d18cf4fefdeec05853c7420cc0499dde1e88b27
License
GPL-3.0
Collected
2026-08-05
Default branch
master
View the original SKILL.md

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

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:

BETTER_AUTH_SECRET=<generated-secret-key>
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/:

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:

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:

// Drizzle
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg", // or "mysql", "sqlite"
  }),
});

// 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",
  }),
});

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

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

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

// server/api/auth/[...all].ts
import { auth } from "~/utils/auth";

export default defineEventHandler((event) => {
  return auth.handler(toWebRequest(event));
});

SvelteKit:

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

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:

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:

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:

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    autoSignIn: true, // default: true
  }
});

Client Usage:

// Sign Up
const { data, error } = await authClient.signUp.email({
  email: "[email protected]",
  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: "[email protected]",
  password: "securePassword123",
  callbackURL: "/dashboard",
  rememberMe: true // default: true
});

Social OAuth

Server Configuration:

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:

await authClient.signIn.social({
  provider: "github",
  callbackURL: "/dashboard",
  errorCallbackURL: "/error",
  newUserCallbackURL: "/welcome",
});

Sign Out

await authClient.signOut({
  fetchOptions: {
    onSuccess: () => {
      router.push("/login");
    }
  }
});

Session Management

Client-Side Session

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

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

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

  if (isPending) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return <div>Welcome, {session?.user.name}!</div>;
}

// Vue
<script setup>
import { authClient } from "~/lib/auth-client";
const session = authClient.useSession();
</script>

<template>
  <div v-if="session.data">{{ session.data.user.email }}</div>
</template>

// Svelte
<script>
import { authClient } from "$lib/auth-client";
const session = authClient.useSession();
</script>

<p>{$session.data?.user.email}</p>

Using getSession:

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

Server-Side Session

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

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

export const auth = betterAuth({
  plugins: [
    twoFactor(),
    organization(),
    username(),
  ]
});

Client-Side:

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:

# Regenerate schema
npx @better-auth/cli generate

# Apply migration
npx @better-auth/cli migrate

Popular Plugins

Two-Factor Authentication (2FA)

// 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

// 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

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)

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

export const auth = betterAuth({
  plugins: [passkey()]
});

// Client
await authClient.passkey.register();
await authClient.passkey.signIn();

Organization/Multi-Tenancy

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: "[email protected]",
  role: "member"
});

Advanced Configuration

Email Verification

export const auth = betterAuth({
  emailVerification: {
    sendVerificationEmail: async ({ user, url }) => {
      await sendEmail(user.email, url);
    },
    sendOnSignUp: true
  }
});

Rate Limiting

export const auth = betterAuth({
  rateLimit: {
    enabled: true,
    window: 60, // seconds
    max: 10 // requests
  }
});

Custom Session Expiration

export const auth = betterAuth({
  session: {
    expiresIn: 60 * 60 * 24 * 7, // 7 days in seconds
    updateAge: 60 * 60 * 24 // Update every 24 hours
  }
});

CORS Configuration

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:

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)

// 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

await authClient.updateUser({
  name: "New Name",
  image: "https://example.com/new-avatar.jpg"
});

Password Management

// Change password
await authClient.changePassword({
  currentPassword: "oldPassword",
  newPassword: "newPassword"
});

// Reset password (forgot password)
await authClient.forgetPassword({
  email: "[email protected]",
  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
  2. Database connection errors

    • Verify database credentials
    • Check if database server is running
    • Ensure correct adapter for your database
  3. CORS errors

    • Configure corsOptions in advanced settings
    • Ensure client and server URLs match
  4. 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

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

Alternatives

Compare before choosing

Computed 10043,034

coreyhaines31/marketingskills

ab-testing

When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

Computed 10023,835

alirezarezvani/claude-skills

app-store-optimization

App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist

Computed 1004,944

dotnet/skills

migrate-vstest-to-mtp

Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing

Computed 100165

JasonColapietro/suede-creator-skills

suede-ab-testing

Suede-owned experimentation discipline for hypotheses, sample sizing, test duration, significance, and repeatable experiment programs. Use when comparing variants, deciding whether a result is reliable, or building an experiment backlog and cadence. NOT FOR: analytics instrumentation (use suede-analytics), post-click conversion diagnosis (use suede-site-alchemy), or writing the variant copy itself (use suede-copy).