golemkit

Core

Authentication

Authentication is Better Auth configured in src/modules/auth/auth.ts — the single source of truth for providers, sessions, and hooks. Three sign-in methods ship enabled:

  • Email + password (with email verification sent on signup).
  • Google OAuth — registers itself only when GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are set; the UI hides the button otherwise.
  • Magic links — "Email me a sign-in link" on the sign-in page.

Reading the session

In server code (pages, layouts, route handlers):

import { getSession, requireSession } from "@/modules/auth";

const session = await getSession();        // Session | null
const session = await requireSession();    // redirects to /sign-in if absent

requireSession() in a layout protects an entire subtree — that's how /dashboard is guarded. In client components, use the hooks from @/modules/auth/auth-client (useSession, signIn, signOut).

Two-layer protection

src/proxy.ts(Next 16's middleware) does a fast, optimistic cookie check and redirects obvious anonymous visitors. The real validation — hitting the database — runs in the layout. Don't move authorization into the proxy; Next.js explicitly recommends against it.

Signup side effects

New users get a 50-credit bonus and a welcome email through Better Auth's databaseHooks.user.create.after — see it in auth.ts. That hook is the right place for any "on signup" behavior (analytics, default workspace rows), keeping it out of the UI flow. The email is fire-and-forget: delivery failures are logged, never surfaced as signup errors.

Account settings

/dashboard/settings ships the screens every SaaS needs: rename, change password (revokes other sessions), change email (confirmed by email), and GDPR-grade account deletion gated by password plus a typed confirmation. Deletion is safe because every user-owned table references user.id with onDelete: "cascade" — credits, transactions, and documents go with the account. The forms live in src/modules/auth/components/settings-forms.tsx; the server side is just user.changeEmail and user.deleteUser enabled in auth.ts.

Auth emails

Magic-link and verification emails go through src/modules/email (Resend). When RESEND_API_KEYis unset they're logged to the server console instead, so the flows stay testable locally without an account.