Authentication
Authentication system built on Better Auth with email/password and OAuth.
Raypx uses Better Auth as its authentication framework. It provides a full-featured auth system with email/password credentials and social OAuth providers, all type-safe out of the box.
What's Configured
The auth system comes pre-configured with three sign-in methods:
Package Structure
Authentication lives in the @raypx/auth workspace package:
Server-Side Setup
The server-side auth instance is created with createAuth() and accessed lazily via getAuth():
export function createAuth() {
const db = createDb()
return betterAuth({
database: drizzleAdapter(db, { provider: "pg", schema }),
emailAndPassword: { enabled: true },
socialProviders: { /* dynamically loaded */ },
plugins: [tanstackStartCookies()],
})
}
let _auth: ReturnType<typeof createAuth> | undefined
export function getAuth() {
if (!_auth) _auth = createAuth()
return _auth
}getAuth() uses a lazy singleton pattern -- the auth instance is only created on first access, not at module load time. This avoids issues with environment variables not being ready during cold starts.
Client-Side Setup
The client-side auth client is created from Better Auth's React integration:
import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient({})This gives you access to hooks like authClient.useSession() and methods like authClient.signIn.email(), authClient.signUp.email(), authClient.signIn.social(), and authClient.signOut().
Auth Route
All Better Auth requests are handled at a single catch-all route:
import { auth } from "@raypx/auth"
export const Route = createFileRoute("/api/auth/$")({
server: {
handlers: {
GET: ({ request }) => auth.handler(request),
POST: ({ request }) => auth.handler(request),
},
},
})Session Handling
Raypx uses the tanstackStartCookies() plugin from Better Auth to manage sessions through TanStack Start's cookie system. Sessions are stored in the session database table and validated on every request to protected routes.