The Auth Problem
Auth0: $23/month for 1,000 users. Clerk: $25/month. NextAuth: works until you need custom logic, then you fight the abstraction.
Lucia is a session management library. Not a framework. Not a service. You control every part of the auth flow.
What Lucia Gives You
Session Management
import { Lucia } from 'lucia';
import { DrizzleSQLiteAdapter } from '@lucia-auth/adapter-drizzle';
const adapter = new DrizzleSQLiteAdapter(db, sessionTable, userTable);
export const lucia = new Lucia(adapter, {
sessionCookie: {
attributes: {
secure: process.env.NODE_ENV === 'production',
},
},
});
Sign Up
import { generateId } from 'lucia';
import { Argon2id } from 'oslo/password';
const hashedPassword = await new Argon2id().hash(password);
const userId = generateId(15);
await db.insert(userTable).values({
id: userId,
email: email,
hashedPassword: hashedPassword,
});
const session = await lucia.createSession(userId, {});
const sessionCookie = lucia.createSessionCookie(session.id);
// Set cookie in response
Sign In
const user = await db.query.userTable.findFirst({
where: eq(userTable.email, email),
});
const validPassword = await new Argon2id().verify(
user.hashedPassword,
password
);
if (validPassword) {
const session = await lucia.createSession(user.id, {});
const cookie = lucia.createSessionCookie(session.id);
// Set cookie
}
Validate Sessions
const sessionId = cookies.get(lucia.sessionCookieName);
const { session, user } = await lucia.validateSession(sessionId);
if (!session) {
// Not authenticated
return redirect('/login');
}
OAuth
import { GitHub } from 'arctic';
const github = new GitHub(clientId, clientSecret);
const url = await github.createAuthorizationURL(state, { scopes: ['user:email'] });
// After callback:
const tokens = await github.validateAuthorizationCode(code);
const githubUser = await fetch('https://api.github.com/user', {
headers: { Authorization: `Bearer ${tokens.accessToken}` },
}).then(r => r.json());
Works With Any Framework
Next.js, SvelteKit, Astro, Express, Hono, Nuxt, Remix — Lucia is framework-agnostic.
Works With Any Database
Drizzle, Prisma, Mongoose, raw SQL, Turso, PlanetScale, Supabase — via adapters.
Why This Matters
Auth services charge per user. Auth frameworks hide the logic. Lucia gives you the tools to build auth exactly how you want it — and you understand every line.
Building authenticated apps? Check out my web scraping actors on Apify Store — data APIs for your user-facing features. For custom solutions, email spinov001@gmail.com.
Top comments (0)