What’s up, devs! 👋
In this post, I’ll walk you through setting up authentication in a Node.js/Next.js project using Better-Auth — a powerful new authentication library. This is based on the first episode of my YouTube playlist Better-Auth Basics.
Better-Auth makes it really easy to implement secure authentication with features like:
- ✅ Email + Password authentication
- ✅ Social sign-ins
- ✅ Built-in rate limiting
- ✅ Automatic database management & adapters
- ✅ Two-factor authentication support
- ✅ Simple client API for frontend integrations
Sounds exciting? Let’s dive in! 🚀
🛠 Project Setup
For this tutorial, I’m working on my personal project — a ride-sharing app.
We’ll integrate Better-Auth into it step by step.
1. Install Dependencies
We’ll need Better-Auth, Drizzle ORM, and Postgres.
bun add better-auth drizzle-orm postgres
2. Environment Variables
Generate a secret key and add it to your .env file:
BETTER_AUTH_SECRET=your-secret-key
BETTER_AUTH_URL=http://localhost:3000 # Base URL of your app
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
⚙️ Database Setup with Drizzle
Better-Auth ships with ready-to-use schemas.
We’ll copy those into our project and run migrations.
1. Generate Schema
bunx @better-auth/cli generate # create better-auth schema
2. Run Migrations
bunx drizzle-kit generate # generate migration files
bunx drizzle-kit migrate
Once done, your database will have all the required tables.
🔑 Enable Email/Password Authentication
Inside your Better-Auth server setup, enable email/password auth:
// lib/auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db"; // your drizzle instance
import * as schema from "@/db/schema"; // your drizzle schema
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg", // or "mysql", "sqlite"
schema,
}),
emailAndPassword: {
enabled: true,
},
});
🖥 Setting Up the Client
Better-Auth provides a client utility to make frontend integration simple.
// lib/auth-client.ts
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
/** The base URL of the server (optional if you're using the same domain) */
baseURL: "http://localhost:3000",
});
📡 Next.js API Routes
Now, let’s connect it with 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);
This route will handle all sign-in, sign-up, and session management APIs.
👤 Implement Sign-Up
On your register page, use the client:
async function handleRegister(e) {
e.preventDefault();
try {
await authClient.signUp.email({
name: form.name,
email: form.email,
password: form.password,
callbackUrl: "/",
});
} catch (err) {
console.error(err);
}
}
🔐 Implement Sign-In
Similarly, on your login page:
async function handleLogin(e) {
e.preventDefault();
try {
await authClient.signIn.email({
email: form.email,
password: form.password,
callbackUrl: "/",
});
} catch (err) {
console.error(err);
}
}
🎉 Testing It Out
- Tried signing up → User was created successfully ✅
- Tried logging in → Redirected to homepage with 200 response ✅
That’s it! We now have a working authentication flow with Better-Auth.
📌 What’s Next?
This tutorial only covers the basics:
- Setting up Better-Auth
- Running database migrations with Drizzle
- Implementing Sign-In & Sign-Up
In upcoming posts/videos, I’ll cover:
- 🔑 Authorization & Role-Based Access
- ⚡ Rate Limiting
- 🔒 Two-Factor Authentication
- 🔗 Social Logins
Stay tuned!
🔗 Connect With Me
👉 If you found this useful, drop a comment and let me know what you’re building with Better-Auth.
And don’t forget to follow me here on DEV.to + subscribe on YouTube for more tutorials.
Happy coding! ✨
Top comments (3)
If you show how the logout route works, then it would be great for me.
Do you need to install something for this (apart from node.js)
You need to install the necessary dependencies, mentioned in the Project Setup step.