Sessions, roles, passkeys, 2FA
Better Auth with a role column the API actually reads. Email and password, OAuth providers, one-time codes, and recovery.
const session = await auth.api.getSession({ headers })
if (session?.user.role !== "admin") redirect("/login")
What a plan is allowed to do
Polar checkout and webhooks land here, and the rest of the app asks this package rather than reading a subscription row.
await can(user, "project.create")
One schema, typed end to end
Drizzle against Postgres. The same types reach the API handler and the React component without a generation step.
export const projects = pgTable("projects", {
ownerId: text("owner_id") .references(() => user.id),
})
Work that outlives a request
A separate process on the same queue, so a slow export or a retrying webhook never holds an HTTP response open.
# one command brings the whole stack up
bun run setup
# docker compose, db:push, db:seed