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 (0)