
Better Auth Core
- 238 installs
- 63 repo stars
- Updated July 18, 2026
- bobmatnyc/claude-mpm-skills
Implement Better Auth core flows—sessions, OAuth providers, email magic links, and account linking—in TypeScript backends for secure SaaS login.
About
Claude MPM skill for Better Auth core: configure adapters, define providers, wire session middleware, and implement secure login, logout, and account flows for TypeScript SaaS, API, and mobile-backed products.
- Better Auth session and cookie setup
- OAuth and social provider configuration
- Email and passwordless patterns
- TypeScript server adapter integration
Better Auth Core by the numbers
- 238 all-time installs (skills.sh)
- Ranked #1,585 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill better-auth-coreAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 238 |
|---|---|
| repo stars | ★ 63 |
| Last updated | July 18, 2026 |
| Repository | bobmatnyc/claude-mpm-skills ↗ |
What it does
Implement Better Auth core flows—sessions, OAuth providers, email magic links, and account linking—in TypeScript backends for secure SaaS login.
Files
Better Auth Core (TypeScript)
Goals
- Set up a Better Auth instance with environment variables and data layer wiring.
- Wire server handlers and a client instance.
- Use sessions and server-side API methods safely.
- Keep data-layer choices pluggable (drivers or adapters).
Quick start
1. Install better-auth. 2. Set BETTER_AUTH_SECRET (32+ chars) and BETTER_AUTH_URL. 3. Create auth.ts and export auth. 4. Provide database (driver or adapter) or omit for stateless sessions. 5. Mount a handler (auth.handler or a framework helper). 6. Create a client with createAuthClient.
import { betterAuth } from "better-auth";
export const auth = betterAuth({
database: myDatabaseOrAdapter, // driver or adapter; omit for stateless mode
emailAndPassword: { enabled: true },
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID as string,
clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
},
},
});Core setup checklist
- Export the instance as
auth(or default export) so helpers find it. - Keep
BETTER_AUTH_URLin sync with the public base URL. - Pass the full base URL to the client if you change the
/api/authbase path. - Add database migrations before enabling plugins that require tables.
Server API usage
- Call server endpoints via
auth.api.*with{ body, headers, query }. - Use
asResponse: trueif you need aResponseobject. - Use
returnHeaders: trueto accessSet-Cookieheaders.
import { auth } from "./auth";
const session = await auth.api.getSession({
headers: request.headers,
});
const response = await auth.api.signInEmail({
body: { email, password },
asResponse: true,
});Session access
- Client:
authClient.useSession()orauthClient.getSession(). - Server:
auth.api.getSession({ headers }).
TypeScript tips
- Infer types with
auth.$InferandauthClient.$Infer. - Use
inferAdditionalFieldson the client when you extend the user schema.
References
toolchains/platforms/auth/better-auth/better-auth-core/references/setup-database.mdtoolchains/platforms/auth/better-auth/better-auth-core/references/client-server.mdtoolchains/platforms/auth/better-auth/better-auth-core/references/typescript.md
{
"name": "better-auth-core",
"version": "1.0.0",
"category": "toolchain",
"toolchain": null,
"tags": [
"better-auth",
"auth",
"typescript",
"core",
"sessions",
"api",
"client",
"server",
"database"
],
"entry_point_tokens": 220,
"full_tokens": 1890,
"related_skills": [
"better-auth-authentication",
"better-auth-integrations",
"better-auth-plugins"
],
"author": "Claude MPM",
"license": "MIT",
"platform": "auth"
}
Client and server usage
Create a client instance
Import the framework-specific client (or the vanilla client) and create the instance.
import { createAuthClient } from "better-auth/client";
export const authClient = createAuthClient({
baseURL: "http://localhost:3000", // optional if same domain
});Framework packages include:
better-auth/reactbetter-auth/vuebetter-auth/sveltebetter-auth/solid
Common client calls
const { data, error } = await authClient.signIn.email({
email,
password,
});
const { data: session } = await authClient.getSession();Use authClient.useSession() for reactive session state in supported frameworks.
Server-side API calls
Call endpoints through auth.api and pass inputs as { body, headers, query }.
import { auth } from "./auth";
const session = await auth.api.getSession({
headers: request.headers,
});
await auth.api.signInEmail({
body: { email, password },
headers: request.headers,
});Return headers or Response
const { headers } = await auth.api.signUpEmail({
returnHeaders: true,
body: { email, password, name },
});
const response = await auth.api.signInEmail({
body: { email, password },
asResponse: true,
});Error handling
import { APIError, isAPIError } from "better-auth/api";
try {
await auth.api.signInEmail({
body: { email, password },
});
} catch (error) {
if (isAPIError(error)) {
console.error(error.message, error.status);
}
}Setup and data layer
Environment variables
Set the required secrets and base URL:
BETTER_AUTH_SECRET=replace-with-32-plus-chars
BETTER_AUTH_URL=http://localhost:3000Create the auth instance
Create auth.ts and export auth (or default export):
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// configure database and auth methods here
});Data layer options
Use either a direct driver or an adapter. Pass it to database.
Direct drivers (examples)
import { betterAuth } from "better-auth";
import Database from "better-sqlite3";
export const auth = betterAuth({
database: new Database("./sqlite.db"),
});import { Pool } from "pg";
import { betterAuth } from "better-auth";
export const auth = betterAuth({
database: new Pool({
// connection options
}),
});import { createPool } from "mysql2/promise";
import { betterAuth } from "better-auth";
export const auth = betterAuth({
database: createPool({
// connection options
}),
});Adapters (examples)
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db";
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg" }),
});import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { PrismaClient } from "@/generated/prisma/client";
const prisma = new PrismaClient();
export const auth = betterAuth({
database: prismaAdapter(prisma, { provider: "sqlite" }),
});import { betterAuth } from "better-auth";
import { mongodbAdapter } from "better-auth/adapters/mongodb";
import { client } from "@/db";
export const auth = betterAuth({
database: mongodbAdapter(client),
});Stateless mode
Omit database for stateless session management. Note that most plugins require a database.
Create tables and migrations
Use the CLI to generate or apply schema changes:
npx @better-auth/cli generatenpx @better-auth/cli migratemigrate is available only for the built-in Kysely adapter. Use generate to create SQL or ORM schema files for manual migrations.
TypeScript and type inference
Infer core types
Use $Infer to extract types from the server or client instance.
import { createAuthClient } from "better-auth/client";
const authClient = createAuthClient();
export type Session = typeof authClient.$Infer.Session;import { betterAuth } from "better-auth";
import Database from "better-sqlite3";
export const auth = betterAuth({
database: new Database("database.db"),
});
type Session = typeof auth.$Infer.Session;Add additional fields
Define additional fields on the user or session and keep them out of user input when needed.
import { betterAuth } from "better-auth";
import Database from "better-sqlite3";
export const auth = betterAuth({
database: new Database("database.db"),
user: {
additionalFields: {
role: {
type: "string",
input: false,
},
},
},
});Infer additional fields on the client
When server and client live in the same project, use inferAdditionalFields.
import { createAuthClient } from "better-auth/react";
import { inferAdditionalFields } from "better-auth/client/plugins";
import type { auth } from "./auth";
export const authClient = createAuthClient({
plugins: [inferAdditionalFields<typeof auth>()],
});When client and server are separate, specify the fields directly.
import { createAuthClient } from "better-auth/client";
import { inferAdditionalFields } from "better-auth/client/plugins";
export const authClient = createAuthClient({
plugins: [
inferAdditionalFields({
user: {
role: { type: "string" },
},
}),
],
});