Better Auth: A Modern Authentication Framework for TypeScript

Explore Better Auth, a comprehensive authentication solution that simplifies user management in modern web applications

Written by

Ankit Sharma

At

Hello

index.js
console.log("Hello World");

In this blog, we’ll:

  • Set up Better Auth in a Next.js app
  • Configure authentication providers
  • Handle sessions on the server and client
  • Build simple sign-in and sign-up flows

All examples use Next.js App Router and TypeScript.


Why Better Auth?

If you’ve used older auth libraries, you’ve probably faced at least one of these:

  • Confusing session handling
  • Too much client-side logic
  • Poor App Router support
  • Over-engineered configs

Better Auth focuses on:

  • Server-first authentication
  • Simple APIs (auth.api.getSession() 👀)
  • Framework-native patterns
  • Minimal boilerplate

Perfect for modern Next.js projects.


Installation

Install Better Auth and its peer dependencies:

npm install better-auth

(If you’re using a database adapter, install that as well — Prisma, Drizzle, etc.)


Creating the Auth Instance

Create a central auth configuration file.

// lib/auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
  appName: "My Next App",
  baseURL: "http://localhost:3000",
  secret: process.env.AUTH_SECRET!,
});

This auth object becomes the single source of truth for authentication across your app.


Setting Up the Auth Route

Better Auth exposes APIs via a route handler.

// app/api/auth/[...all]/route.ts
import { auth } from "@/lib/auth";

export const GET = auth.handler;
export const POST = auth.handler;

That’s it. No giant config files, no custom controllers.


Sign Up & Sign In (Client Side)

Here’s a simple sign-in example using a client component.

"use client";

import { authClient } from "better-auth/client";

export function SignInButton() {
  const signIn = async () => {
    await authClient.signIn.email({
      email: "user@example.com",
      password: "password123",
    });
  };

  return <button onClick={signIn}>Sign In</button>;
}

Better Auth handles cookies and sessions automatically.


Getting the Session (Server Side)

This is where Better Auth really shines.

Instead of messy helpers, you simply do:

// app/dashboard/page.tsx
import { auth } from "@/lib/auth";

export default async function DashboardPage() {
  const session = await auth.api.getSession();

  if (!session) {
    return <div>Not authenticated</div>;
  }

  return (
    <div>
      <h1>Welcome, {session.user.email}</h1>
    </div>
  );
}

No middleware hacks. No client-side fetching.


Protecting Routes

You can protect routes at page level or using middleware.

const session = await auth.api.getSession();
if (!session) redirect("/login");

Simple, readable, and explicit.


Getting Session on the Client

If you do need session data on the client:

"use client";

import { useSession } from "better-auth/client";

export function UserInfo() {
  const { data: session, isLoading } = useSession();

  if (isLoading) return <p>Loading...</p>;
  if (!session) return <p>Not logged in</p>;

  return <p>{session.user.email}</p>;
}

Signing Out

await authClient.signOut();

Clean. Predictable. No surprises.


Common Mistake (and Fix)

Wrong way (server-side):

getServerSession(); // ❌ not needed

Correct way:

await auth.api.getSession();

If you’re using Better Auth — use Better Auth everywhere.


When Should You Use Better Auth?

Better Auth is a great choice if:

  • You’re using Next.js App Router
  • You prefer server-side auth
  • You want clean, minimal APIs
  • You don’t want to fight your auth library

For side projects, startups, and even serious products — it scales nicely.


Final Thoughts

Authentication shouldn’t be the hardest part of your app.

Better Auth keeps things:

  • Simple
  • Modern
  • Aligned with Next.js

If you’re building projects like dashboards, ERPs, LMS platforms, or SaaS apps — this is a solid foundation.

Happy building 🚀