better-auth

create-auth-skill

77
4
# Install this skill:
npx skills add better-auth/skills --skill "create-auth-skill"

Install specific skill from multi-skill repository

# Description

Skill for creating auth layers in TypeScript/JavaScript apps using Better Auth.

# SKILL.md


name: create-auth-skill
description: Skill for creating auth layers in TypeScript/JavaScript apps using Better Auth.


Create Auth Skill

Guide for adding authentication to TypeScript/JavaScript applications using Better Auth.

For code examples and syntax, see better-auth.com/docs.


Decision Tree

Is this a new/empty project?
β”œβ”€ YES β†’ New project setup
β”‚   1. Identify framework
β”‚   2. Choose database
β”‚   3. Install better-auth
β”‚   4. Create auth.ts + auth-client.ts
β”‚   5. Set up route handler
β”‚   6. Run CLI migrate/generate
β”‚   7. Add features via plugins
β”‚
└─ NO β†’ Does project have existing auth?
    β”œβ”€ YES β†’ Migration/enhancement
    β”‚   β€’ Audit current auth for gaps
    β”‚   β€’ Plan incremental migration
    β”‚   β€’ See migration guides in docs
    β”‚
    └─ NO β†’ Add auth to existing project
        1. Analyze project structure
        2. Install better-auth
        3. Create auth config
        4. Add route handler
        5. Run schema migrations
        6. Integrate into existing pages

Installation

Core: npm install better-auth

Scoped packages (as needed):
| Package | Use case |
|---------|----------|
| @better-auth/passkey | WebAuthn/Passkey auth |
| @better-auth/sso | SAML/OIDC enterprise SSO |
| @better-auth/stripe | Stripe payments |
| @better-auth/scim | SCIM user provisioning |
| @better-auth/expo | React Native/Expo |


Environment Variables

BETTER_AUTH_SECRET=<32+ chars, generate with: openssl rand -base64 32>
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL=<your database connection string>

Add OAuth secrets as needed: GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GOOGLE_CLIENT_ID, etc.


Server Config (auth.ts)

Location: lib/auth.ts or src/lib/auth.ts

Minimal config needs:
- database - Connection or adapter
- emailAndPassword: { enabled: true } - For email/password auth

Standard config adds:
- socialProviders - OAuth providers (google, github, etc.)
- emailVerification.sendVerificationEmail - Email verification handler
- emailAndPassword.sendResetPassword - Password reset handler

Full config adds:
- plugins - Array of feature plugins
- session - Expiry, cookie cache settings
- account.accountLinking - Multi-provider linking
- rateLimit - Rate limiting config

Export types: export type Session = typeof auth.$Infer.Session


Client Config (auth-client.ts)

Import by framework:
| Framework | Import |
|-----------|--------|
| React/Next.js | better-auth/react |
| Vue | better-auth/vue |
| Svelte | better-auth/svelte |
| Solid | better-auth/solid |
| Vanilla JS | better-auth/client |

Client plugins go in createAuthClient({ plugins: [...] }).

Common exports: signIn, signUp, signOut, useSession, getSession


Route Handler Setup

Framework File Handler
Next.js App Router app/api/auth/[...all]/route.ts toNextJsHandler(auth) β†’ export { GET, POST }
Next.js Pages pages/api/auth/[...all].ts toNextJsHandler(auth) β†’ default export
Express Any file app.all("/api/auth/*", toNodeHandler(auth))
SvelteKit src/hooks.server.ts svelteKitHandler(auth)
SolidStart Route file solidStartHandler(auth)
Hono Route file auth.handler(c.req.raw)

Next.js Server Components: Add nextCookies() plugin to auth config.


Database Migrations

Adapter Command
Built-in Kysely npx @better-auth/cli@latest migrate (applies directly)
Prisma npx @better-auth/cli@latest generate --output prisma/schema.prisma then npx prisma migrate dev
Drizzle npx @better-auth/cli@latest generate --output src/db/auth-schema.ts then npx drizzle-kit push

Re-run after adding plugins.


Database Adapters

Database Setup
SQLite Pass better-sqlite3 or bun:sqlite instance directly
PostgreSQL Pass pg.Pool instance directly
MySQL Pass mysql2 pool directly
Prisma prismaAdapter(prisma, { provider: "postgresql" }) from better-auth/adapters/prisma
Drizzle drizzleAdapter(db, { provider: "pg" }) from better-auth/adapters/drizzle
MongoDB mongodbAdapter(db) from better-auth/adapters/mongodb

Common Plugins

Plugin Server Import Client Import Purpose
twoFactor better-auth/plugins twoFactorClient 2FA with TOTP/OTP
organization better-auth/plugins organizationClient Teams/orgs
admin better-auth/plugins adminClient User management
bearer better-auth/plugins - API token auth
openAPI better-auth/plugins - API docs
passkey @better-auth/passkey passkeyClient WebAuthn
sso @better-auth/sso - Enterprise SSO

Plugin pattern: Server plugin + client plugin + run migrations.


Auth UI Implementation

Sign in flow:
1. signIn.email({ email, password }) or signIn.social({ provider, callbackURL })
2. Handle error in response
3. Redirect on success

Session check (client): useSession() hook returns { data: session, isPending }

Session check (server): auth.api.getSession({ headers: await headers() })

Protected routes: Check session, redirect to /sign-in if null.


Security Checklist

  • [ ] BETTER_AUTH_SECRET set (32+ chars)
  • [ ] advanced.useSecureCookies: true in production
  • [ ] trustedOrigins configured
  • [ ] Rate limits enabled
  • [ ] Email verification enabled
  • [ ] Password reset implemented
  • [ ] 2FA for sensitive apps
  • [ ] CSRF protection NOT disabled
  • [ ] account.accountLinking reviewed

Troubleshooting

Issue Fix
"Secret not set" Add BETTER_AUTH_SECRET env var
"Invalid Origin" Add domain to trustedOrigins
Cookies not setting Check baseURL matches domain; enable secure cookies in prod
OAuth callback errors Verify redirect URIs in provider dashboard
Type errors after adding plugin Re-run CLI generate/migrate

Resources

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.