Modern Authentication Solutions for JavaScript Developers
Javascript | Nexsaar
Smart Prototyping in Figma: If-Else Logic & Conditionals

Let’s be honest authentication in the JavaScript world has always felt… messy. You either hack together a bunch of libraries that barely fit, or hand over everything to a SaaS and hope you don’t regret the vendor lock-in (or the bill).
That’s where Better Auth steps in. It’s not just “yet another auth library.” It’s framework-agnostic, lives inside your app, keeps user data in your database, and comes with a plugin system for advanced features all without charging you per user.
In this post, I’ll walk you through why Better Auth feels different, how to get started with dead-simple snippets, and some real-world flows you’ll actually use daily.
Why devs are hyped about Better Auth
-
Works anywhere: Next.js, Remix, Nuxt, SvelteKit, Express, Hono, Fastify bring your own framework.
-
Ready out of the box: Email+password, social logins, 2FA, passkeys, multi-session support, orgs/roles, rate limiting the works.
-
Plugin-first mindset: Add features via plugins instead of reinventing the wheel.
-
Your data, your rules: Users live in your DB. No “per-MAU” billing nonsense.
-
Full control: Tweak flows, cookies, endpoints, and types however you want.
Quick start with Next.js (zero → sign-in)
Step 1: Install it
pnpm add better-auth
# npm i better-auth
# yarn add better-auth
# bun add better-authStep 2: Create your auth instance
// lib/auth.ts
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
autoSignIn: false, // sign-in after sign-up is manual now
},
plugins: [nextCookies()], // last plugin sets Next.js cookies automatically
});Step 3: Hook it up to Next.js routes
// app/api/auth/[...all]/route.ts
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export const { GET, POST } = toNextJsHandler(auth.handler)Core flows you’ll actually use
Email & Password (Next.js + Server Actions)
// app/(auth)/actions.ts
"use server";
import { auth } from "@/lib/auth";
export async function signUp(formData: FormData) {
await auth.api.signUpEmail({
body: {
email: String(formData.get("email")),
password: String(formData.get("password")),
},
});
}
export async function signIn(formData: FormData) {
await auth.api.signInEmail({
body: {
email: String(formData.get("email")),
password: String(formData.get("password")),
},
});
}Social Login (GitHub example)
// lib/auth.ts
export const auth = betterAuth({
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
});Client button:
// app/sign-in/SignInButtons.tsx
"use client";
import { authClient } from "@/lib/auth-client";
export function SignInButtons() {
return (
<button
onClick={() =>
authClient.signIn.social({
provider: 'github',
callbackURL: '/dashboard',
errorCallbackURL: '/error',
newUserCallbackURL: '/welcome',
})
}
>
Continue with GitHub
</button>
)
}Session handling
Client side:
// app/_components/User.tsx
"use client";
import { authClient } from "@/lib/auth-client";
export function User() {
const { data: session, isPending } = authClient.useSession()
if (isPending) return null
return session ? (
<span>{session.user.email}</span>
) : (
<button onClick={() => authClient.signOut()}>Sign out</button>
)
}Server side:
// app/dashboard/page.tsx
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
export default async function DashboardPage() {
const session = await auth.api.getSession({ headers: await headers() })
if (!session) return null // or redirect("/sign-in")
return <div>Welcome {session.user.email}</div>
}Leveling up with plugins
Want 2FA? Drop it in.
Need passkeys? One line.
API keys? Done.
// lib/auth.ts
import { betterAuth } from "better-auth";
import { twoFactor } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [twoFactor()],
});On the client:
// lib/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { twoFactorClient } from "better-auth/client/plugins";
export const authClient = createAuthClient({
plugins: [twoFactorClient({ twoFactorPage: "/two-factor" })],
});Production tips for Next.js
-
Mount routes with toNextJsHandler(auth.handler) under /api/auth/[...all].
-
Cookies are secure + httpOnly by default. Tweak useSecureCookies if needed.
-
Cross-domain? Configure trustedOrigins and your framework’s CORS.
-
Use middleware for fast redirects; use auth.api.getSession() for strict validation.
-
Full TypeScript support, with types inferred from your auth instance.
Why Better Auth feels like a game-changer
-
One mental model across frameworks move code without rewriting auth.
-
Batteries included but still extensible.
-
No lock-in, no surprise costs you own your stack.
If you’re kicking off a new project or tired of bending Auth0/Clerk/NextAuth to your will, Better Auth makes authentication less painful, more flexible, and dev-friendly from day one.