Example Docs

Integrations

Better Auth is framework-agnostic but provides first-class integrations for popular frameworks.

Supported Frameworks

FrameworkHandlerClient SDK
Next.jstoNextJsHandlerbetter-auth/react
NuxttoH3Handlerbetter-auth/vue
SvelteKittoSvelteKitHandlerbetter-auth/svelte
AstroBuilt-in supportbetter-auth/react or vanilla
ExpresstoNodeHandlerAny client SDK
HonotoHonoHandlerAny client SDK
Elysia (Bun)toElysiaHandlerAny client SDK
FastifytoNodeHandlerAny client SDK

Next.js

API Route

// app/api/auth/[...all]/route.ts
import { auth } from "@/auth";
import { toNextJsHandler } from "better-auth/next-js";

export const { GET, POST } = toNextJsHandler(auth);

Middleware

// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export async function middleware(request: NextRequest) {
  const session = request.cookies.get("better-auth.session_token");

  if (!session && request.nextUrl.pathname.startsWith("/dashboard")) {
    return NextResponse.redirect(new URL("/sign-in", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard/:path*"],
};

Server Components

import { auth } from "@/auth";
import { headers } from "next/headers";

export default async function Page() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  return <div>Hello, {session?.user.name ?? "Guest"}!</div>;
}

Nuxt

Server Plugin

// server/plugins/auth.ts
import { auth } from "~/auth";
import { toH3Handler } from "better-auth/h3";

export default defineNitroPlugin((nitroApp) => {
  nitroApp.h3App.use("/api/auth/**", toH3Handler(auth));
});

Composable

<script setup lang="ts">
import { useSession } from "better-auth/vue";

const { data: session, pending } = useSession();
</script>

<template>
  <div v-if="pending">Loading...</div>
  <div v-else-if="session">Hello, {{ session.user.name }}!</div>
  <div v-else>Not signed in</div>
</template>

Express / Node.js

import express from "express";
import { auth } from "./auth";
import { toNodeHandler } from "better-auth/node";

const app = express();

// Mount auth handler
app.all("/api/auth/*", toNodeHandler(auth));

// Protected route example
app.get("/api/me", async (req, res) => {
  const session = await auth.api.getSession({
    headers: req.headers,
  });

  if (!session) {
    return res.status(401).json({ error: "Unauthorized" });
  }

  res.json({ user: session.user });
});

app.listen(3000);

Hono

import { Hono } from "hono";
import { auth } from "./auth";

const app = new Hono();

app.on(["POST", "GET"], "/api/auth/**", (c) => {
  return auth.handler(c.req.raw);
});

export default app;

SvelteKit

Server Hook

// src/hooks.server.ts
import { auth } from "$lib/auth";

export async function handle({ event, resolve }) {
  const session = await auth.api.getSession({
    headers: event.request.headers,
  });

  event.locals.session = session;
  return resolve(event);
}

Page

<script>
  import { useSession } from "better-auth/svelte";
  const session = useSession();
</script>

{#if $session}
  <p>Welcome, {$session.user.name}!</p>
{:else}
  <p>Please sign in.</p>
{/if}