Authentication
Authentication is handled by Better Auth, configured in
server/utils/auth.ts.
Supported sign-in methods
- Email + password, with forgot-password and email verification
- Magic link (passwordless)
- Google OAuth (set
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRETto enable) - TOTP two-factor authentication with backup codes
- Passkeys (WebAuthn)
Reading the session
Always read the session with useCurrentSession() (app/utils/auth-client.ts), not
authClient.useSession() directly — it dedupes the request across middleware, layout,
and page so a single navigation only hits /api/auth/get-session once.
Teams and roles
Users can belong to multiple organizations, switch between them, and invite teammates
with owner/admin/member roles. Granular permissions are defined in
shared/utils/permissions.ts using Better Auth's real access-control system, not a
hardcoded role-name comparison.
Protecting a route
definePageMeta({
layout: 'dashboard',
middleware: 'auth'
})
Server routes call requireSession(event) (server/utils/session.ts), which also
accepts a valid x-api-key header — see Public API.